using Nirvana.Common;
using Nirvana.Common.ApiBase;
using Nirvana.Data;
using Senparc.Weixin.WxOpen.Containers;
using Senparc.Weixin.WxOpen.Helpers;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YBDevice.Entity;

namespace YBDevice.Api.DBServices
{
    /// <summary>
    /// 注册用户管理
    /// </summary>
    public partial class UserApp : BaseApp
    {
        /// <summary>
        /// 获取用户个人资料
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> GetUserInfoAsync()
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                var user = await dbClient.Queryable<YB_RegUser>().Where(x => x.Id == authInfo.UserId).FirstAsync();
                var family = await dbClient.Queryable<YB_Family>().Where(x => x.UserId == user.Id).OrderBy(x => x.LastHeartTime, OrderByType.Desc).FirstAsync();
                var target = await dbClient.Queryable<YB_FamilyTarget>().FirstAsync(x => x.familyid == family.Id);
                var data = new UserInfoModel
                {
                    headimg = user.Headimg,
                    sex = user.Gender,
                    nickname = user.Name,
                    isbindphone = string.IsNullOrEmpty(user.Phone) ? false : true,
                    age = family.Age,
                    familyid = family.Id,
                    height = family.Height,
                    targetweight = target != null ? target.weight : 0,
                    targettime = target != null ? target.time.ToString("yyyy-MM-dd") : "",
                    weight = family.Weight,
                    lasthearttime = family.LastHeartTime.HasValue ? family.LastHeartTime.Value.ToString("yyyy-MM-dd") : ""
                };
                return new ResultInfo(ResultState.SUCCESS, "success", data);
            }
        }

        /// <summary>
        /// 解密手机号
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> DecryptPhoneAsync(WxOpenDecryptSubmitModel model)
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                var sessionBag = await SessionContainer.GetSessionAsync(model.sessionId);
                if (sessionBag == null)
                {
                    return new ResultInfo(ResultState.FAIL, "sessionId未找到");
                }
                var phone = EncryptHelper.DecryptPhoneNumber(model.sessionId, model.encryptedData, model.iv);
                //更新当前用户的手机号
                await dbClient.Updateable<YB_RegUser>().SetColumns(x => new YB_RegUser
                {
                    Phone = phone.purePhoneNumber
                }).Where(x => x.Id == authInfo.UserId).ExecuteCommandAsync();
                return new ResultInfo(ResultState.SUCCESS, "手机号绑定成功");
            }
        }

        /// <summary>
        /// 获取用户测量数据
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> GetMeasureInfoAsync(UserMeasureInfoModel model)
        {
            if (model.height <= 0)
            {
                return new ResultInfo(ResultState.FAIL, "身高不可小于0");
            }
            if (model.age <= 0)
            {
                return new ResultInfo(ResultState.FAIL, "年龄不可小于0");
            }
            using (var dbClient = ReadDbContext.GetInstance())
            {
                //获取此家庭成员的体重信息
                var family = await dbClient.Queryable<YB_Family>().Where(x => x.Id == model.familyid).FirstAsync();
                if (family == null)
                {
                    return new ResultInfo(ResultState.FAIL, "家庭成员未找到");
                }
                if (!await dbClient.Queryable<YB_Measure>().AnyAsync(x => x.FamilyId == family.Id))
                {
                    return new ResultInfo(ResultState.FAIL, "此家庭成员还未分配测量记录");
                }
                var result = await dbClient.Queryable<YB_ResultExt>().Where(x => SqlFunc.Subqueryable<YB_Measure>().Where(e => e.ResultId == x.ResultId && e.FamilyId == family.Id).Any())
                    .OrderBy(x => x.CreateTime, OrderByType.Desc)
                    .FirstAsync();
                var data = BodyFatHelper.CalcBodyFat(family.Weight.ToDouble(), model.height, model.age, result.Imp.ToInt(), model.sex);
                var returndata = new UserMeasureInfo
                {
                    bmi = data.bmi,
                    bmiLevel = data.bmiLevel,
                    body = data.body,
                    bodyage = data.bodyage,
                    bodyageLevel = data.bodyageLevel,
                    bodylevel = data.bodylevel,
                    bone = data.bone,
                    boneLevel = data.boneLevel,
                    cmi = data.cmi,
                    fatLevel = data.fatLevel,
                    fatlevel = data.fatlevel,
                    fat_r = data.fat_r,
                    fat_rLevel = data.fat_rLevel,
                    fat_w = data.fat_w,
                    fat_wLevel = data.fat_wLevel,
                    kcal = data.kcal,
                    kcalLevel = data.kcalLevel,
                    lbm = data.lbm,
                    muscle = data.muscle,
                    muscleLevel = data.muscleLevel,
                    muscleval = data.muscleval,
                    musulevalLevel = data.musulevalLevel,
                    protein = data.protein,
                    proteinLevel = data.proteinLevel,
                    proteinval = data.proteinval,
                    proteinvalLevel = data.proteinvalLevel,
                    sfr = data.sfr,
                    sfrLevel = data.sfrLevel,
                    standardbmi = data.standardbmi,
                    standardbody = data.standardbody,
                    standardbodyage = data.standardbodyage,
                    standardbone = data.standardbone,
                    standardfatlevel = data.standardfatlevel,
                    standardfat_r = data.standardfat_r,
                    standardfat_w = data.standardfat_w,
                    standardkcal = data.standardkcal,
                    standardlbm = data.standardlbm,
                    standardmuscle = data.standardmuscle,
                    standardmuscleval = data.standardmuscleval,
                    standardprotein = data.standardprotein,
                    standardproteinval = data.standardproteinval,
                    standardsfr = data.standardsfr,
                    standardviscera = data.standardviscera,
                    standardwater = data.standardwater,
                    standardWeight = data.standardWeight,
                    visceral = data.visceral,
                    visceralLevel = data.visceralLevel,
                    water = data.water,
                    waterLevel = data.waterLevel
                };
                //获取每项的历史值
                var dataset = await dbClient.Ado.UseStoredProcedure().GetDataSetAllAsync("proc_getmeasureitem_page", new
                {
                    pagesize = model.pagesize,
                    pagenum = model.pagenum,
                    familyid = model.familyid
                });
                if (dataset.Tables.Count == 0)
                {
                    returndata.list = new List<MeasureInfoItem>();
                }
                else
                {
                    //BMI标准,最大值,最小值,标准范围
                    var listcnt = DataTableListHelper.ToList<MeasureModels>(dataset.Tables[0]);
                    var listday = DataTableListHelper.ToList<MeasureModels>(dataset.Tables[1]);
                    List<MeasureInfoItem> info = new List<MeasureInfoItem>();
                    List<string> mlist = new List<string> { "bmi", "fat_r", "muscle", "water", "bone", "kcal", "fat_w", "visceral", "protein", "bodyage","sfr","body",
                        "muscleval","proteinval","lbm","fatlevel" };
                    //最近的上上次测量结果
                    var lastresult = await dbClient.Queryable<YB_ResultExt>().Where(x => SqlFunc.Subqueryable<YB_Measure>().Where(e => e.ResultId == x.ResultId && e.FamilyId == family.Id).Any() && x.ResultId != result.ResultId)
                        .OrderBy(x => x.CreateTime, OrderByType.Desc)
                        .FirstAsync();
                    if (lastresult != null)
                    {
                        var mresult = await dbClient.Queryable<YB_Measure>().Where(x => x.ResultId == lastresult.ResultId).FirstAsync();
                        var levelresult = BodyFatHelper.CalcBodyFat(lastresult.Weight.ToDouble(), mresult.Height, mresult.Age, lastresult.Imp.ToInt(), mresult.Sex);
                        //判定时sex为0-女，1-男，所以这里进行转换
                        model.sex = model.sex == 2 ? 0 : 1;
                        mlist.ForEach(x =>
                        {
                            var m = new MeasureInfoItem()
                            {
                                name = x
                            };
                            if (x == "bmi")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.bmi.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.bmi.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.bmi_value(model.sex, model.age);
                                m.value = levelresult.bmi;
                                m.lastvalue = data.bmi - m.value;
                            }
                            else if (x == "fat_r")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.fat_r.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.fat_r.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.fa_r_value(model.sex, model.age);
                                m.value = levelresult.fat_r;
                                m.lastvalue = data.fat_r - m.value;
                            }
                            else if (x == "muscle")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.muscle.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.muscle.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.muscle_value(model.sex, model.age);
                                m.value = levelresult.muscle;
                                m.lastvalue = data.muscle - m.value;
                            }
                            else if (x == "water")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.water.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.water.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.water_value(model.sex, model.age);
                                m.value = levelresult.water;
                                m.lastvalue = data.water - m.value;
                            }
                            else if (x == "bone")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.bone.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.bone.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.bone_value(model.sex, model.age, lastresult.Weight);
                                m.value = levelresult.bone;
                                m.lastvalue = data.bone - m.value;
                            }
                            else if (x == "kcal")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.kcal.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.kcal.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.kcal_value(model.sex, model.age, lastresult.Weight);
                                m.value = levelresult.kcal;
                                m.lastvalue = data.kcal - m.value;
                            }
                            else if (x == "fat_w")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.fat_w.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.fat_w.ToString(), time = e.timestamp }).ToList();
                                m.value = levelresult.fat_w;
                                m.lastvalue = data.fat_w - m.value;
                            }
                            else if (x == "visceral")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.visceral.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.visceral.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.visceral_value(model.sex, model.age);
                                m.value = levelresult.visceral;
                                m.lastvalue = data.visceral - m.value;
                            }
                            else if (x == "protein")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.protein.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.protein.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.protein_value(model.sex, model.age);
                                m.value = levelresult.protein;
                                m.lastvalue = data.protein - m.value;
                            }
                            else if (x == "bodyage")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.bodyage.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.bodyage.ToString(), time = e.timestamp }).ToList();
                                m.value = levelresult.bodyage;
                                m.lastvalue = data.bodyage - m.value;
                            }
                            else if (x == "sfr")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.sfr.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.sfr.ToString(), time = e.timestamp }).ToList();
                                m.slist = BodyFatHelper.sfr_value(model.sex, model.age);
                                m.value = levelresult.sfr;
                                m.lastvalue = data.sfr - m.value;
                            }
                            else if (x == "body")
                            {
                                m.list = listcnt
                                .Select(e => new MeasureHisItem { value = e.body, time = e.timestamp })
                                .ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.body, time = e.timestamp }).ToList();
                                m.value = 0;
                                m.lastvalue = 0;
                            }
                            else if (x == "muscleval")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.muscleval.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.muscleval.ToString(), time = e.timestamp }).ToList();
                                m.value = levelresult.muscleval;
                                m.lastvalue = data.muscleval - m.value;
                            }
                            else if (x == "proteinval")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.proteinval.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.proteinval.ToString(), time = e.timestamp }).ToList();
                                m.value = levelresult.proteinval;
                                m.lastvalue = data.proteinval - m.value;
                            }
                            else if (x == "lbm")
                            {
                                m.list = listcnt.Select(e => new MeasureHisItem { value = e.lbm.ToString(), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = e.lbm.ToString(), time = e.timestamp }).ToList();
                                m.value = levelresult.lbm;
                                m.lastvalue = data.lbm - m.value;
                            }
                            else if (x == "fatlevel")
                            {
                                m.list = listcnt
                                .Select(e => new MeasureHisItem { value = BodyFatHelper.fatlevel(e.fatlevel.ToDouble()), time = e.timestamp }).ToList();
                                m.daylist = listday.Select(e => new MeasureHisItem { value = BodyFatHelper.fatlevel(e.fatlevel.ToDouble()), time = e.timestamp }).ToList();
                                m.value = levelresult.fatlevel;
                                m.lastvalue = data.fatlevel - m.value;
                            }
                            info.Add(m);
                        });
                        returndata.list = info;
                    }
                }
                return new ResultInfo(ResultState.SUCCESS, "success", returndata);
            }
        }
    }
}
