using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YBDevice.Entity;

namespace YBDevice.NApi.Application.LXBodyInfo
{
    /// <summary>
    /// 丽秀体质计算
    /// </summary>
    public class LXBodyService : BaseService, ILXBodyService, ITransient
    {
        private readonly ISqlSugarRepository<YB_LXBodyType> repository;
        private readonly SqlSugarClient dbClient;
        public LXBodyService(ISqlSugarRepository<YB_LXBodyType> sqlSugarRepository)

        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
        }
        /// <summary>
        /// 获取已经计算的结果
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> GetInfoAsync()
        {
            var result = await dbClient.Queryable<YB_LXBodyResult>().Where(x => x.UserId == authInfo.UserId).ToListAsync();
            //获取结果
            if (result != null && result.Count > 0)
            {
                var data = await GetBodyTypeAsync(result);
                return new ResultInfo(ResultState.SUCCESS, "计算成功", data);
            }
            else
            {
                return new ResultInfo(ResultState.FAIL, "抱歉,体质评估失败");
            }
        }
        /// <summary>
        /// 体质结果
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private async Task<LXBodySubmitResultData> GetBodyTypeAsync(List<YB_LXBodyResult> result)
        {
            var ids = result.Select(x => x.TypeId).ToList();
            var guidlist = await dbClient.Queryable<YB_LXBodyGuide>().Where(x => ids.Contains(x.TypeId)).ToListAsync();
            var types = await dbClient.Queryable<YB_LXBodyType>().Where(x => ids.Contains(x.Id)).ToListAsync();
            List<LXBodySubmitResult> returndata = new List<LXBodySubmitResult>();
            string bodytype = string.Empty;
            string bodytype1 = string.Empty;
            bool hasqx = false;
            bool hasy = false;

            var phtype = types.FirstOrDefault(x => x.IsPH == 1);
            //如果有基本上是平和质
            if (phtype != null)
            {
                var phdata = result.FirstOrDefault(x => x.TypeId == phtype.Id && x.Result == 2);
                if (phdata != null)
                {
                    bodytype1 = $"您基本上是";
                }
                else
                {
                    bodytype1 = $"您是";
                }
            }

            //如果倾向体质都是是有八种,则全部显示，否则展示前四项。
            int cnt = result.Where(x => x.Result == 1).Count();
            if (cnt > 1 && cnt < 8)
            {
                var scorelist = await dbClient.Queryable<YB_LXBodyAns>()
                    .Where(x => x.UserId == authInfo.UserId)
                    .OrderBy(x => x.RealScore, OrderByType.Desc)
                    .Take(4)
                    .Select(x => x.TypeId)
                    .ToListAsync();
                Guid toptypeid = scorelist.FirstOrDefault();
                var topresult = result.FirstOrDefault(x => x.TypeId == toptypeid);
                result = result.Where(x => scorelist.Contains(x.TypeId)).ToList();
                result.ForEach(x => { 
                    if(x.TypeId != toptypeid)
                    {
                        x.Result = 2;
                    }
                });
            }
            result.ForEach(x =>
            {
                var guild = guidlist.Where(e => e.TypeId == x.TypeId).FirstOrDefault();
                var type = types.Where(e => e.Id == x.TypeId).FirstOrDefault();

                if (guild != null)
                {
                    returndata.Add(new LXBodySubmitResult
                    {
                        Result = x.Result,
                        Sick = guild.Sick,
                        Feature = guild.Feature,
                        BodyType = x.BodyType,
                        Health = guild.Health,
                        People = guild.People
                    });
                    if (x.Result == 1)
                    {
                        hasy = true;
                    }
                    if (x.Result == 2)
                    {
                        hasqx = true;
                    }
                    if (string.IsNullOrEmpty(bodytype))
                    {
                        bodytype += x.Result == 1 ? $"" : $"有{type.Name},";
                    }
                    else if (x.Result == 2)
                    {
                        bodytype += $"{type.Name},";

                    }
                    if (string.IsNullOrEmpty(bodytype1))
                    {
                        bodytype1 += x.Result == 1 ? $"您是{type.Name}," : $"";
                    }
                    else if (x.Result == 1)
                    {
                        bodytype1 += $"{type.Name},";
                    }
                }
            });
            bodytype = !string.IsNullOrEmpty(bodytype) ? bodytype.Substring(0, bodytype.Length - 1) : "";
            bodytype1 = !string.IsNullOrEmpty(bodytype1) ? bodytype1.Substring(0, bodytype1.Length - 1) : "";
            if (hasqx)
            {
                bodytype += "体质倾向";
            }
            if (hasy)
            {
                bodytype1 += "体质";
            }
            var data = new LXBodySubmitResultData
            {
                BodyType = bodytype1,
                extinfo = bodytype,
                list = returndata
            };
            return data;
        }

        /// <summary>
        /// 判断体质
        /// </summary>
        /// <returns></returns>
        private async Task<List<YB_LXBodyResult>> CalcBodyTypeAsync()
        {
            List<YB_LXBodyResult> resultlist = new List<YB_LXBodyResult>();
            if (await dbClient.Queryable<YB_LXBodyAns>().Where(x => x.UserId == authInfo.UserId).CountAsync() == 9)
            {
                //计算最终的结果
                var phdata = await dbClient.Queryable<YB_LXBodyType>().FirstAsync(x => x.IsPH == 1);//平和质ID
                var scorelist = await dbClient.Queryable<YB_LXBodyAns>()
                        .Where(x => x.UserId == authInfo.UserId).ToListAsync();
                var phscore = scorelist.FirstOrDefault(x => x.TypeId == phdata.Id).RealScore;//平和质转化分
                var newscorelist = scorelist.Where(x => x.TypeId != phdata.Id)
                    .OrderByDescending(x => x.RealScore)
                    .ToList();

                //如果平和质转化分>=60,,其他体质<30,是平和质
                if (phscore >= 60 && newscorelist.Where(x => x.RealScore < 30).Count() == 8)
                {
                    resultlist.Add(new YB_LXBodyResult
                    {
                        Id = IDGen.NextID(),
                        BodyType = phdata.Name,
                        CreateTime = DateTime.Now,
                        FamilyId = 0,
                        Result = 1,
                        TypeId = phdata.Id,
                        UserId = authInfo.UserId
                    });
                }
                //如果平和质转化分>=60,,其他体质<40,基本是平和质
                else
                {
                    //判断平和质
                    if (phscore >= 60 && newscorelist.Where(x => x.RealScore < 40).Count() == 8)
                    {
                        resultlist.Add(new YB_LXBodyResult
                        {
                            Id = IDGen.NextID(),
                            BodyType = phdata.Name,
                            CreateTime = DateTime.Now,
                            FamilyId = 0,
                            Result = 2,
                            TypeId = phdata.Id,
                            UserId = authInfo.UserId
                        });
                    }
                    //判断非平和质体质
                    for (var i = 0; i < newscorelist.Count; i++)
                    {
                        var score = newscorelist[i];
                        //如果有一个>=40,则判断为是
                        if (score.RealScore >= 40)
                        {
                            var scoredata = await dbClient.Queryable<YB_LXBodyType>().FirstAsync(x => x.Id == score.TypeId);
                            resultlist.Add(new YB_LXBodyResult
                            {
                                Id = IDGen.NextID(),
                                BodyType = scoredata.Name,
                                CreateTime = DateTime.Now,
                                FamilyId = 0,
                                Result = 1,
                                TypeId = scoredata.Id,
                                UserId = authInfo.UserId
                            });
                        }
                        else if (score.RealScore <= 39 && score.RealScore >= 30)
                        {
                            var scoredata = await dbClient.Queryable<YB_LXBodyType>().FirstAsync(x => x.Id == score.TypeId);
                            resultlist.Add(new YB_LXBodyResult
                            {
                                Id = IDGen.NextID(),
                                BodyType = scoredata.Name,
                                CreateTime = DateTime.Now,
                                FamilyId = 0,
                                Result = 2,
                                TypeId = scoredata.Id,
                                UserId = authInfo.UserId
                            });
                        }
                    }
                }
                //保存结果
                await dbClient.Deleteable<YB_LXBodyResult>().Where(x => x.UserId == authInfo.UserId).ExecuteCommandAsync();
                if (resultlist.Count > 0)
                {
                    await dbClient.Insertable(resultlist).ExecuteCommandAsync();
                }
            }
            return resultlist;
        }
        /// <summary>
        /// 问答列表
        /// </summary>
        /// <param name="isrestart">是否重新计算,0-否,1-是</param>
        /// <param name="sex">性别,1-男,2-女,0-未知</param>
        /// <returns></returns>
        public async Task<ResultInfo> GetListAsync(int isrestart = 0, int sex = 0)
        {
            if (isrestart == 1)
            {
                await dbClient.Deleteable<YB_LXBodyAns>().Where(x => x.UserId == authInfo.UserId).ExecuteCommandAsync();
            }
            var tempquery = dbClient.Queryable<YB_LXBodyQA>();
            if (sex > 0)
            {
                tempquery = tempquery.Where(x => x.IsSex == 0 || x.IsSex == sex);
            }
            //LXBodyList
            var list = await dbClient.Queryable<YB_LXBodyType>()
                .Select(x => new LXBodyList
                {
                    Id = x.Id,
                    Name = x.Name
                })
                .ToListAsync();
            var qaquery = await tempquery.ToListAsync();
            list.ForEach(x =>
            {
                x.qalist = qaquery.Where(e => e.TypeId == x.Id)
                .OrderBy(e => e.SortCode)
                .Select(e => new LXBodyQAList
                {
                    Title = e.Title,
                    AlWaysValue = e.AlWaysValue,
                    Id = e.Id,
                    LittleValue = e.LittleValue,
                    NoneValue = e.NoneValue,
                    OftenValue = e.OftenValue,
                    SomeValue = e.SomeValue
                }).ToList();
            });
            return new ResultInfo(ResultState.SUCCESS, "success", list);
        }
        /// <summary>
        /// 结果计算
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetResultInfoAsync(LXBodySubmitDto data)
        {
            if (data == null)
            {
                return new ResultInfo(ResultState.FAIL, "请先完成问答");
            }
            var qalist = await dbClient.Queryable<YB_LXBodyQA>().Where(x => x.TypeId == data.id).ToListAsync();
            int score = 0;//原始分
            data.list.ForEach(x =>
            {
                var item = qalist.FirstOrDefault(x => x.Id == x.Id);
                int val = item != null ? Score(item.IsRequired, x.Score) : 0;
                score += val;
            });
            int cnt = qalist.Count;//条目数
            int realscore = ((score - cnt) / (cnt * 4)) * 100;//转化分
                                                              //添加记录
            var insertdata = new YB_LXBodyAns
            {
                CreateTime = DateTime.Now,
                Score = score,
                RealScore = realscore,
                FamilyId = 0,
                Id = IDGen.NextID(),
                TypeId = data.id,
                UserId = authInfo.UserId
            };
            await dbClient.Insertable(insertdata).ExecuteCommandAsync();
            //检查是否已计算完整
            if (await dbClient.Queryable<YB_LXBodyAns>().Where(x => x.UserId == authInfo.UserId).CountAsync() == 9)
            {
                var result = await CalcBodyTypeAsync();
                if (result != null && result.Count > 0)
                {
                    var datas = await GetBodyTypeAsync(result);
                    return new ResultInfo(ResultState.SUCCESS, "计算成功", datas);
                }
                else
                {
                    return new ResultInfo(ResultState.FAIL, "抱歉,体质评估失败");
                }
            }
            return new ResultInfo(ResultState.FAIL, "请先完成问答");
        }
        /// <summary>
        /// 分数计算
        /// </summary>
        /// <param name="isrequired">是否需要逆向,1-是,0-否</param>
        /// <param name="score">分数</param>
        /// <returns></returns>
        private int Score(int isrequired, int score)
            => (isrequired, score) switch
            {
                _ when isrequired == 1 && score == 1 => 5,
                _ when isrequired == 1 && score == 2 => 4,
                _ when isrequired == 1 && score == 3 => 3,
                _ when isrequired == 1 && score == 4 => 2,
                _ when isrequired == 1 && score == 5 => 1,
                _ => score
            };
        /// <summary>
        /// 结果计算
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetResultInfoAsync(List<LXBodySubmitDto> data)
        {
            if (data == null || data.Count != 9)
            {
                return new ResultInfo(ResultState.FAIL, "请先完成问答");
            }
            List<YB_LXBodyAns> insertlist = new List<YB_LXBodyAns>();
            foreach (var item in data)
            {
                var qalist = await dbClient.Queryable<YB_LXBodyQA>().Where(x => x.TypeId == item.id).ToListAsync();
                int score = 0;//原始分
                bool issex = false;//是否有性别区分,如果有则条目数减一
                item.list.ForEach(x =>
                {
                    var items = qalist.FirstOrDefault(e => e.Id == x.Id);
                    int val = items != null ? Score(items.IsRequired, x.Score) : 0;
                    score += val;
                    if (item != null && items.IsSex != 0)
                    {
                        issex = true;
                    }
                });
                int cnt = qalist.Count;//条目数
                cnt = issex ? cnt - 1 : cnt;
                int realscore = ((((score - cnt).ToDecimal()) / ((cnt * 4).ToDecimal())) * 100).ToInt();//转化分
                realscore = realscore < 0 ? 0 : realscore;
                //添加记录
                var insertdata = new YB_LXBodyAns
                {
                    CreateTime = DateTime.Now,
                    Score = score,
                    RealScore = realscore,
                    FamilyId = 0,
                    Id = IDGen.NextID(),
                    TypeId = item.id,
                    UserId = authInfo.UserId
                };
                insertlist.Add(insertdata);
            }
            await dbClient.Deleteable<YB_LXBodyAns>().Where(x => x.UserId == authInfo.UserId).ExecuteCommandAsync();
            await dbClient.Insertable(insertlist).ExecuteCommandAsync();
            var result = await CalcBodyTypeAsync();
            if (result != null && result.Count > 0)
            {
                var datas = await GetBodyTypeAsync(result);
                return new ResultInfo(ResultState.SUCCESS, "计算成功", datas);
            }
            else
            {
                return new ResultInfo(ResultState.FAIL, "计算失败");
            }
        }
    }
}
