using Furion.DependencyInjection;
using SqlSugar;
using YB.DeviceStand.Domain;
using YB.DeviceStand.Domain.Shared;
using YB.DeviceStand.Util.Extend;

namespace YB.DeviceStand.Application.Level
{
    /// <summary>
    /// 计算等级信息
    /// </summary>
    public class LevelService : ILevelService, ITransient
    {
        private readonly ISqlSugarRepository<YB_BmiStand> _bmisRep;//bmi标准仓储
        private readonly ISqlSugarRepository<YB_NewHeightStand> _heightsRep;
        private readonly ISqlSugarRepository<YB_NewWeightStand> _weightsRep;
        private readonly ISqlSugarRepository<YB_HeadStand> _headsRep;
        public LevelService(ISqlSugarRepository<YB_BmiStand> bmisRep, ISqlSugarRepository<YB_NewHeightStand> heigthsRep, ISqlSugarRepository<YB_NewWeightStand> weightsRep,
            ISqlSugarRepository<YB_HeadStand> headsRep)
        {
            _bmisRep = bmisRep;
            _heightsRep = heigthsRep;
            _weightsRep = weightsRep;
            _headsRep = headsRep;
        }
        /// <summary>
        /// 计算等级标准
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public Task<LevelInfoS2SDto> LevelAsync(LevelS2SDto data)
        {
            decimal month = data.Birthday.ToMonth(true);
        }
        /// <summary>
        /// 计算等级标准
        /// </summary>
        /// <param name="sex">性别,1-男,2-女</param>
        /// <param name="month">月龄</param>
        /// <param name="value">BMI值</param>
        /// <param name="type">1-bmi,2-身高,3-体重,4-头围</param>
        /// <returns></returns>
        public async Task<LevelS2SDto> LevelAsync(UserSex sex, decimal month, decimal value, UserResultType type)
        {
            YB_NewHeightStand data = null;
            if (type == UserResultType.Bmi)
            {
                //如果年龄小于6个月则使用6个月的标准
                if (month < 6)
                {
                    data = await _bmisRep.Context.Queryable<YB_BmiStand>().Where(x => x.Sex == (int)sex && x.Month <= 6).OrderBy(x => x.Month, OrderByType.Desc)
                   .Select(x => new YB_NewHeightStand
                   {
                       f1sd = x.f1sd,
                       median = x.median,
                       z1sd = x.z1sd,
                       z2sd = x.z2sd
                   })
                   .FirstAsync();
                }
                else
                {
                    data = await _bmisRep.Context.Queryable<YB_BmiStand>().Where(x => x.Sex == (int)sex && x.Month <= month).OrderBy(x => x.Month, OrderByType.Desc)
                    .Select(x => new YB_NewHeightStand
                    {
                        f1sd = x.f1sd,
                        median = x.median,
                        z1sd = x.z1sd,
                        z2sd = x.z2sd
                    })
                    .FirstAsync();
                }
            }
            else if (type == UserResultType.Height)
            {
                data = await _weightsRep.Context.Queryable<YB_NewHeightStand>().Where(x => x.Sex == (int)sex && x.Month <= month).OrderBy(x => x.Month, OrderByType.Desc)
                    .Select(x => new YB_NewHeightStand
                    {
                        f3sd = x.f3sd,
                        f2sd = x.f2sd,
                        f1sd = x.f1sd,
                        median = x.median,
                        z1sd = x.z1sd,
                        z2sd = x.z2sd,
                        z3sd = x.z3sd
                    })
                    .FirstAsync();
            }
            else if (type == UserResultType.Weight)
            {
                //如果月龄小于0.25则使用0.25的
                month = month < 0.25m ? 0.25m : month;
                data = await _weightsRep.Context.Queryable<YB_NewWeightStand>().Where(x => x.Sex == (int)sex && x.Month <= month).OrderBy(x => x.Month, OrderByType.Desc)
                    .Select(x => new YB_NewHeightStand
                    {
                        f3sd = x.f3sd,
                        f2sd = x.f2sd,
                        f1sd = x.f1sd,
                        median = x.median,
                        z1sd = x.z1sd,
                        z2sd = x.z2sd,
                        z3sd = x.z3sd
                    })
                    .FirstAsync();
            }
            else if (type == UserResultType.Head)
            {
                data = await _headsRep.Context.Queryable<YB_HeadStand>().Where(x => x.Sex == (int)sex && x.Month <= month).OrderBy(x => x.Month, OrderByType.Desc)
                   .Select(x => new YB_NewHeightStand
                   {
                       f3sd = x.f3sd,
                       f2sd = x.f2sd,
                       f1sd = x.f1sd,
                       median = x.median,
                       z1sd = x.z1sd,
                       z2sd = x.z2sd,
                       z3sd = x.z3sd
                   })
                   .FirstAsync();
            }
            var returndata = new LevelInfoS2SDto
            {
                Level = GetLevelVal(data, value, type),
                list = data == null ? new List<LevelValS2SDto>() : GetStandList(data, type),
                Media = data == null ? data.median : 0
            };
            //如果年龄大于16岁则使用成人BMI标准
            if (month > 16 * 12)
            {
                if (type == 1)
                {
                    returndata.list = _bodyFatHelperService.bmi_value(sex, 0).Select(x => new MeasureInfoItemValue
                    {
                        color = x.color,
                        maxvalue = x.maxvalue,
                        minvalue = x.minvalue,
                        text = x.text
                    }).ToList();
                    returndata.Media = _bodyFatHelperService.bmi_stand(sex, 0).minvalue;
                }
            }
            else
            {
                if (data == null)
                {
                    return new LevelS2SDto();
                }
            }
            returndata.Color = GetLevelColor(returndata.Level, type);
            return returndata;
        }
        /// <summary>
        /// 获取等级值
        /// </summary>
        /// <param name="data"></param>
        /// <param name="val">当前值</param>
        /// <param name="type">1-bmi,2-身高,3-体重,4-头围</param>
        /// <returns></returns>
        private string GetLevelVal(YB_NewHeightStand data, decimal val, UserResultType type = UserResultType.Bmi)
            => (data, val, type) switch
            {
                _ when data == null => LevelConst.Error,
                _ when type == UserResultType.Bmi && val <= data.f1sd && val > 0 => BMILevelConst.Thin,
                _ when type == UserResultType.Bmi && val <= data.median && val > data.f1sd => BMILevelConst.Normal,
                _ when type == UserResultType.Bmi && val <= data.z1sd && val > data.median => BMILevelConst.OverWeight,
                _ when type == UserResultType.Bmi && val > data.z1sd => BMILevelConst.Fat,
                //_ when type == 2 && val <= data.f3sd && val > 0 => HeightLevelConst.MoreLow,
                _ when type == UserResultType.Height && val <= data.f2sd && val > 0 => HeightLevelConst.Low,
                _ when type == UserResultType.Height && val <= data.f1sd && val > data.f2sd => HeightLevelConst.LittleLow,
                _ when type == UserResultType.Height && val <= data.median && val > data.f1sd => HeightLevelConst.Normal,
                _ when type == UserResultType.Height && val <= data.z1sd && val > data.median => HeightLevelConst.LittleHeight,
                _ when type == UserResultType.Height && val > data.z1sd => HeightLevelConst.Height,
                //_ when type == 2 && val > data.f2sd => HeightLevelConst.MoreHeight,
                //_ when type == 3 && val <= data.f3sd && val > 0 => WeightLevelConst.MoreLow,
                _ when type == UserResultType.Weight && val <= data.f2sd && val > 0 => WeightLevelConst.Low,
                _ when type == UserResultType.Weight && val <= data.f1sd && val > data.f2sd => WeightLevelConst.LittleLow,
                _ when type == UserResultType.Weight && val <= data.median && val > data.f1sd => WeightLevelConst.Normal,
                _ when type == UserResultType.Weight && val <= data.z1sd && val > data.median => WeightLevelConst.LittleHeight,
                _ when type == UserResultType.Weight && val > data.z1sd => WeightLevelConst.Height,
                //_ when type == 3 && val > data.z2sd => WeightLevelConst.MoreHeight,
                //_ when type == 4 && val <= data.f3sd && val > 0 => HeadLevelConst.MoreLow,
                _ when type == UserResultType.Head && val <= data.f2sd && val > 0 => HeadLevelConst.Low,
                _ when type == UserResultType.Head && val <= data.f1sd && val > data.f2sd => HeadLevelConst.LittleLow,
                _ when type == UserResultType.Head && val <= data.median && val > data.f1sd => HeadLevelConst.Normal,
                _ when type == UserResultType.Head && val <= data.z1sd && val > data.median => HeadLevelConst.LittleHeight,
                _ when type == UserResultType.Head && val > data.z1sd => HeadLevelConst.Height,
                //_ when type == 4 && val > data.z2sd => HeadLevelConst.MoreHeight,
                _ => LevelConst.Error
            };

        /// <summary>
        /// 获取标准列表
        /// </summary>
        /// <param name="data"></param>
        /// <param name="type">1-bmi,2-身高,3-体重,4-头围</param>
        /// <returns></returns>
        private List<LevelValS2SDto> GetStandList(YB_NewHeightStand data, UserResultType type = UserResultType.Bmi)
            => type switch
            {
                UserResultType.Bmi => new List<LevelValS2SDto> {
                    new LevelValS2SDto{
                        maxvalue = data.f1sd,
                        minvalue=0,
                        text = BMILevelConst.Thin,
                        color = LevelColor.Thin
                    },
                    new LevelValS2SDto{
                        maxvalue = data.median,
                        minvalue=data.f1sd,
                        text = BMILevelConst.Normal,
                        color = LevelColor.Normal
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z1sd,
                        minvalue=data.median,
                        text = BMILevelConst.OverWeight,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = 50,
                        minvalue=data.z1sd,
                        text = BMILevelConst.Fat,
                        color = LevelColor.Fat
                    }
                },
                UserResultType.Height => new List<LevelValS2SDto> {
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.f3sd,
                    //    minvalue=0,
                    //    text = HeightLevelConst.MoreLow,
                    //    color = LevelColor.Fat
                    //},
                    new LevelValS2SDto{
                        maxvalue = data.f2sd,
                        minvalue=0,
                        text = HeightLevelConst.Low,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = data.f1sd,
                        minvalue=data.f2sd,
                        text = HeightLevelConst.LittleLow,
                        color = LevelColor.Thin
                    },
                    new LevelValS2SDto{
                        maxvalue = data.median,
                        minvalue=data.f1sd,
                        text = HeightLevelConst.Normal,
                        color = LevelColor.Normal
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z1sd,
                        minvalue=data.median,
                        text = HeightLevelConst.LittleHeight,
                        color = LevelColor.LittleFine
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z3sd,
                        minvalue=data.z1sd,
                        text = HeightLevelConst.Height,
                        color = LevelColor.MoreFine
                    },
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.z3sd,
                    //    minvalue=data.z2sd,
                    //    text = HeightLevelConst.MoreHeight,
                    //    color = LevelColor.Fine
                    //}
                },
                UserResultType.Weight => new List<LevelValS2SDto> {
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.f3sd,
                    //    minvalue=0,
                    //    text = WeightLevelConst.MoreLow,
                    //    color = LevelColor.Fat
                    //},
                    new LevelValS2SDto{
                        maxvalue = data.f2sd,
                        minvalue=0,
                        text = WeightLevelConst.Low,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = data.f1sd,
                        minvalue=data.f2sd,
                        text = WeightLevelConst.LittleLow,
                        color = LevelColor.Thin
                    },
                    new LevelValS2SDto{
                        maxvalue = data.median,
                        minvalue=data.f1sd,
                        text = WeightLevelConst.Normal,
                        color = LevelColor.Normal
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z1sd,
                        minvalue=data.median,
                        text = WeightLevelConst.LittleHeight,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z3sd,
                        minvalue=data.z1sd,
                        text = WeightLevelConst.Height,
                        color = LevelColor.Fat
                    },
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.z3sd,
                    //    minvalue=data.z2sd,
                    //    text = WeightLevelConst.MoreHeight,
                    //    color = LevelColor.Fat
                    //}
                },
                UserResultType.Head => new List<LevelValS2SDto> {
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.f3sd,
                    //    minvalue=0,
                    //    text = HeadLevelConst.MoreLow,
                    //    color = LevelColor.Fat
                    //},
                    new LevelValS2SDto{
                        maxvalue = data.f2sd,
                        minvalue=0,
                        text = HeadLevelConst.Low,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = data.f1sd,
                        minvalue=data.f2sd,
                        text = HeadLevelConst.LittleLow,
                        color = LevelColor.Thin
                    },
                    new LevelValS2SDto{
                        maxvalue = data.median,
                        minvalue=data.f1sd,
                        text = HeadLevelConst.Normal,
                        color = LevelColor.Normal
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z1sd,
                        minvalue=data.median,
                        text = HeadLevelConst.LittleHeight,
                        color = LevelColor.OverWeight
                    },
                    new LevelValS2SDto{
                        maxvalue = data.z3sd,
                        minvalue=data.z1sd,
                        text = HeadLevelConst.Height,
                        color = LevelColor.Fat
                    },
                    //new MeasureInfoItemValue{
                    //    maxvalue = data.z3sd,
                    //    minvalue=data.z2sd,
                    //    text = HeadLevelConst.MoreHeight,
                    //    color = LevelColor.Fat
                    //}
                },
                _ => new List<LevelValS2SDto>()
            };
    }
}
