using Furion.DependencyInjection;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using Nirvana.Common.Extend;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Senparc.CO2NET.Extensions;
using YBDevice.Application.Excel;
using YBDevice.Body.BodyFatHelper;
using YBDevice.CommonService;
using YBDevice.Entity;

namespace YBDevice.Application.MeasureInfo
{
    /// <summary>
    /// 测量记录
    /// </summary>
    public class ResultService : IResultService, ITransient
    {
        private readonly ISqlSugarRepository<YB_nResult> repository;
        private readonly SqlSugarClient dbClient;
        private readonly ICommonService _commonService;
        private readonly IBodyFatHelperService _bodyFatHelperService;
        private readonly IExcelService _excelService;
        private readonly OperatorModel currentUser;

        public ResultService(ISqlSugarRepository<YB_nResult> sqlSugarRepository, ICommonService commonService, IBodyFatHelperService bodyFatHelperService, IExcelService excelService)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            _commonService = commonService;
            _bodyFatHelperService = bodyFatHelperService;
            currentUser = BaseInfoService.GetUserInfo();
            _excelService = excelService;
        }

        /// <summary>
        /// 查询记录详情
        /// </summary>
        /// <param name="id">记录ID</param>
        /// <returns></returns>
        public async Task<UserMeasureDetailDto> GetDetailAsync(Guid id)
        {
            var userresult = await dbClient.Queryable<YB_nUserResult>().FirstAsync(x => x.Id == id);
            if (userresult == null)
            {
                return null;
            }
            YB_Family family = null;
            if (userresult.FamilyId <= 0)
            {
                family = await dbClient.Queryable<YB_Family>().FirstAsync(x => x.UserId == userresult.UserId && x.IsSelf == 1);
            }
            else
            {
                family = await dbClient.Queryable<YB_Family>().FirstAsync(x => x.Id == userresult.FamilyId);
            }
            if (family == null)
            {
                return null;
            }
            YB_RegUser user = null;
            if (family != null)
            {
                user = await dbClient.Queryable<YB_RegUser>().FirstAsync(x => x.Id == family.UserId);
            }
            var res = await dbClient.Queryable<YB_nMeasureResult>().FirstAsync(x => x.Id == id);
            if (res == null)
            {
                return null;
            }
            if (res.Age <= 0)
            {
                res.Age = family.Birthday.ToAge(res.createtime);
            }
            if (res.Sex == GenderType.UnKnow)
            {
                res.Sex = family.Sex;
            }
            var result = await dbClient.Queryable<YB_nResult>().Where(x => x.Id == id).FirstAsync();
            var data = await _bodyFatHelperService.CalcBody120FatAsync(result.Weight, result.Height, res.Age, (GenderType)res.Sex, result.LeftArmImp, result.RightArmImp, result.LeftLegImp, result.RightArmImp, result.Imp);

            var returndata = new UserMeasureDetailDto
            {
                bmi = data.bmi,
                sfr = res.sfr,
                bodyage = res.bodyage,
                bodylevel = res.body,
                bone = res.bone,
                cmi = res.cmi,
                fat_r = res.fat_r,
                fat_w = res.fat_w,
                kcal = res.kcal,
                lbm = res.lbm,
                muscle = res.muscle,
                muscleval = res.muscleval,
                protein = res.protein,
                visceral = res.visceral,
                water = res.water,
                weight = res.Weight,
                type = (int)ResultType.Single,
                HeadImg = family != null ? family.HeadImg : DefaultService.HeadImg(GenderType.Male, FamilyType.Adult),
                NickName = family != null ? family.Name : "",
                Time = res.createtime.ToString("yyyy/MM/dd HH:mm:ss"),
                Phone = user != null ? user.Phone : "",
                Sex = res.Sex,
                Age = res.Age,
                Height = res.Height,
                proteinval = res.proteinval,
                sfrval = res.SfrVal,
                SkeletalMuscle = res.SkeletalMuscle,
                bodyfatkgleftarm = res.LeftHandFatVal,
                bodyfatkgleftleg = res.LeftFootFatVal,
                bodyfatkgrightarm = res.RightHandFatVal,
                bodyfatkgrightleg = res.RightFootFatVal,
                bodyfatkgtrunk = res.BodyFatVal,
                bodyfatrateleftleg = res.LeftFootFat,
                bodyfatrateleftarm = res.LeftHandFat,
                bodyfatraterightarm = res.RightHandFat,
                bodyfatraterightleg = res.RightFootFat,
                bodyfatraterunk = res.BodyFat,
                idealweight = data.idealweight,
                musclekgleftarm = res.LeftHandMuscleVal,
                musclekgleftleg = res.LeftFootMuscleVal,
                musclekgrightarm = res.RightHandMuscleVal,
                musclekgrightleg = res.RightFootMuscleVal,
                musclekgtrunk = res.BodyMuscleVal,
                musclerateleftarm = res.LeftHandMuscle,
                musclerateleftleg = res.LeftFootMuscle,
                muscleraterightarm = res.RightHandMuscle,
                muscleraterightleg = res.RightFootMuscle,
                muscleratetrunk = res.BodyMuscle
            };
            //性别进行转换,使用的0-女,1-男
            GenderType sex = (GenderType)returndata.Sex;
            returndata.values = new MeasureValueDto
            {
                bmi_value = _bodyFatHelperService.bmi_value(sex, returndata.Age),
                sfr_value = _bodyFatHelperService.sfr_value(sex, returndata.Age),
                bone_value = _bodyFatHelperService.bone_value(sex, returndata.Age, returndata.weight),
                fat_w_value = _bodyFatHelperService.fat_w_value(sex, returndata.Age, returndata.weight),
                fa_r_value = _bodyFatHelperService.fa_r_value(sex, returndata.Age),
                kcal_value = _bodyFatHelperService.kcal_value(sex, returndata.Age, returndata.weight),
                muscleval_value = _bodyFatHelperService.muscleval_value(sex, returndata.Age, returndata.weight),
                muscle_value = _bodyFatHelperService.muscle_value(sex, returndata.Age),
                proteinval_value = _bodyFatHelperService.proteinval_value(sex, returndata.Age, returndata.weight),
                protein_value = _bodyFatHelperService.protein_value(sex, returndata.Age),
                visceral_value = _bodyFatHelperService.visceral_value(sex, returndata.Age),
                water_value = _bodyFatHelperService.water_value(sex, returndata.Age),
                sfrval_value = _bodyFatHelperService.sfrval_value(sex, returndata.Age, returndata.weight),
                skeletalmusclekg_value = _bodyFatHelperService.skeletalmusclekg_val(sex, returndata.Age, returndata.SkeletalMuscle)
            };
            return returndata;
        }

        /// <summary>
        /// 根据设备查询测量记录列表
        /// </summary>
        /// <param name="devid"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<MeasureUserListDto>> GetDevResultAsync(int devid, QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_nUserResult, YB_nResult, YB_nMeasureResult>((s, r, m) => new JoinQueryInfos(
                 JoinType.Left, s.Id == r.Id,
                 JoinType.Left, r.Id == m.Id
             )).Where((s, r, m) => r.EquId == devid);
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        if (x.Name == "createtime")
                        {
                            if (x.Type == 3)
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime >= SqlFunc.ToDate(x.Value));
                            }
                            else
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime <= SqlFunc.ToDate(x.Value));
                            }
                        }
                        else
                        {
                            conModels.Add(new ConditionalModel()
                            {
                                FieldName = x.Name,
                                ConditionalType = (ConditionalType)x.Type,
                                FieldValue = x.Value.Trim()
                            });
                        }
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            var query = await temquery.OrderBy((s, r, m) => r.CreateTime, OrderByType.Desc)
                 .Select((s, r, m) => new MeasureUserListDto
                 {
                     Month = m.Month,
                     sfr = m.sfr,
                     bmi = m.bmi,
                     fatlevel = m.fatlevel,
                     fat_r = m.fat_r,
                     fat_w = m.fat_w,
                     body = m.body,
                     bodyage = m.bodyage,
                     bone = m.bone,
                     cmi = m.cmi,
                     createtime = SqlFunc.ToString(r.CreateTime),
                     Height = r.Height,
                     kcal = m.kcal,
                     lbm = m.lbm,
                     id = r.Id,
                     muscle = m.muscle,
                     muscleval = m.muscleval,
                     protein = m.protein,
                     proteinval = m.proteinval,
                     visceral = m.visceral,
                     water = m.water,
                     weight = m.Weight,
                     userid = s.UserId,
                     familyid = s.FamilyId,
                     sex = m.Sex,
                     DevType = s.DevType
                 })
                .Mapper((it, cache) =>
                {
                    it.Age = it.Month.TomAge();
                    it.createtime = it.createtime.ToYearDateTime();
                    var alluser = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.userid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_RegUser>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var allfamily = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.familyid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_Family>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var user = alluser.FirstOrDefault(x => x.Id == it.userid);
                    var family = allfamily.FirstOrDefault(x => x.Id == it.familyid);
                    it.headimg = user != null ? user.Headimg : "";
                    if (family != null && family.IsSelf == 1)
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}";
                    }
                    else
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}({(family != null ? family.Name : "")})";
                    }
                    it.phone = user != null ? user.Phone : "";
                })
                .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<MeasureUserListDto>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }

        /// <summary>
        /// 测量记录列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<MeasureUserListDto>> GetListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_nUserResult, YB_nResult, YB_nMeasureResult>((s, r, m) => new JoinQueryInfos(
                 JoinType.Left, s.Id == r.Id,
                  JoinType.Left, r.Id == m.Id
              )).Where((s, r, m) => s.UserId > 0);
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        if (x.Name == "createtime")
                        {
                            if (x.Type == 3)
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime >= SqlFunc.ToDate(x.Value));
                            }
                            else
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime <= SqlFunc.ToDate(x.Value));
                            }
                        }
                        else if (x.Name.ToLower() == "facecode")
                        {
                            temquery = temquery.Where((s, r, m) => SqlFunc.Subqueryable<YB_Device>().Where(e => e.FacCode == x.Value && e.Id == r.EquId).Any());
                        }
                        else if (x.Name.ToLower() == "devtype")
                        {
                            int type = x.Value.ToInt();
                            temquery = temquery.Where((s, r, m) => s.DevType == type);
                        }
                        else
                        {
                            if (x.Name.ToLower() != "name")
                            {
                                conModels.Add(new ConditionalModel()
                                {
                                    FieldName = x.Name,
                                    ConditionalType = (ConditionalType)x.Type,
                                    FieldValue = x.Value.Trim()
                                });
                            }
                        }
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            if (currentUser.AccountType != AccountType.platform)
            {
                temquery = temquery.Where((s, r, m) => r.BusinessId == currentUser.BusinessId
                || SqlFunc.Subqueryable<YB_DeviceAlloc>().Where(e => e.EquId == r.EquId && (e.ToBusinessId == currentUser.BusinessId || e.FromBusinessId == currentUser.BusinessId)).Any()
                || SqlFunc.Subqueryable<YB_Device>().Where(e => e.Id == r.EquId && e.BindBusinessId == currentUser.BusinessId).Any()
                );
            }
            bool isshowphone = currentUser.AccountType == AccountType.platform || BusinessShowConst.PhoneShowIds.Contains(currentUser.BusinessId);
            bool isshowbodytype = currentUser.AccountType == AccountType.platform || BusinessShowConst.BodyTypeShowIds.Contains(currentUser.BusinessId);
            var query = await temquery.OrderBy((s, r, m) => r.CreateTime, OrderByType.Desc)
                 .Select((s, r, m) => new MeasureUserListDto
                 {
                     Month = m.Month,
                     sfr = m.sfr,
                     bmi = m.bmi,
                     fatlevel = m.fatlevel,
                     fat_r = m.fat_r,
                     fat_w = m.fat_w,
                     body = m.body,
                     bodyage = m.bodyage,
                     bone = m.bone,
                     cmi = m.cmi,
                     createtime = SqlFunc.ToString(r.CreateTime),
                     Height = r.Height,
                     kcal = m.kcal,
                     lbm = m.lbm,
                     id = r.Id,
                     muscle = m.muscle,
                     muscleval = m.muscleval,
                     protein = m.protein,
                     proteinval = m.proteinval,
                     visceral = m.visceral,
                     water = m.water,
                     weight = m.Weight,
                     userid = s.UserId,
                     familyid = s.FamilyId,
                     sex = m.Sex,
                     equid = r.EquId,
                     Businesid = r.BusinessId,
                     DevType = s.DevType
                 })
                .Mapper((it, cache) =>
                {
                    var allequ = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.equid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Device>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.devname = allequ.FirstOrDefault(x => x.Id == it.equid)?.Name;
                    it.facecode = allequ.FirstOrDefault(x => x.Id == it.equid)?.FacCode;
                    var allbusiness = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.Businesid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.BusinessName = allbusiness.FirstOrDefault(x => x.Id == it.Businesid)?.Name;
                    it.Age = it.Month.TomAge();
                    it.createtime = it.createtime.ToYearDateTime();
                    var alluser = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.userid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_RegUser>().Where(x => ids.Contains(x.Id))
                        .Select(x => new YB_RegUser
                        {
                            Id = x.Id,
                            Headimg = x.Headimg,
                            Name = x.Name,
                            Phone = x.Phone
                        })
                        .ToList();
                    });

                    var allfamily = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.familyid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_Family>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var user = alluser.FirstOrDefault(x => x.Id == it.userid);
                    var family = allfamily.FirstOrDefault(x => x.Id == it.familyid);
                    it.headimg = user != null ? user.Headimg : "";
                    if (family != null && family.IsSelf == 1)
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}";
                    }
                    else
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}({(family != null ? family.Name : "")})";
                    }
                    it.phone = user != null && isshowphone ? user.Phone : "";
                    if (currentUser.AccountType == AccountType.platform || isshowbodytype)
                    {
                        var allbodytype = cache.Get(list =>
                        {
                            var ids = list.Where(x => x.userid > 0).Select(x => x.userid).ToList();
                            return dbClient.Queryable<YB_LXBodyResult>().Where(x => ids.Contains(x.UserId)).ToList();
                        });
                        var results = allbodytype.Where(x => x.UserId == it.userid).ToList();
                        if (results != null && results.Count > 0)
                        {
                            var ids = results.Select(x => x.TypeId).ToList();
                            var guidlist = dbClient.Queryable<YB_LXBodyGuide>().Where(x => ids.Contains(x.TypeId)).ToList();
                            results.ForEach(x =>
                            {
                                var guild = guidlist.Where(e => e.TypeId == x.TypeId).FirstOrDefault();
                                if (guild != null)
                                {
                                    it.BodyType += $"{BodyType(x.BodyType, x.Result)},";
                                }
                            });
                            it.BodyType = it.BodyType.Substring(0, it.BodyType.Length - 1);
                        }
                    }
                })
                .ToPageListAsync(param.offset, param.limit, totalnum);

            //return new PageParms<MeasureUserListDto>
            //{
            //    page = param.offset,
            //    Items = c,
            //    totalnum = totalnum,
            //    limit = param.limit
            //};

            var totalnum2 = totalnum;

            var query2 = await temquery.OrderBy((s, r, m) => r.CreateTime, OrderByType.Desc)
                .Select((s, r, m) => new MeasureUserListDto
                {
                    Month = m.Month,
                    sfr = m.sfr,
                    bmi = m.bmi,
                    fatlevel = m.fatlevel,
                    fat_r = m.fat_r,
                    fat_w = m.fat_w,
                    body = m.body,
                    bodyage = m.bodyage,
                    bone = m.bone,
                    cmi = m.cmi,
                    createtime = SqlFunc.ToString(r.CreateTime),
                    Height = r.Height,
                    kcal = m.kcal,
                    lbm = m.lbm,
                    id = r.Id,
                    muscle = m.muscle,
                    muscleval = m.muscleval,
                    protein = m.protein,
                    proteinval = m.proteinval,
                    visceral = m.visceral,
                    water = m.water,
                    weight = m.Weight,
                    userid = s.UserId,
                    familyid = s.FamilyId,
                    sex = m.Sex,
                    equid = r.EquId,
                    Businesid = r.BusinessId,
                    DevType = s.DevType
                })
               .Mapper((it, cache) =>
               {
                   var allequ = cache.Get(list =>
                   {
                       var ids = list.Select(x => x.equid).ToList().IDistinctList();
                       return dbClient.Queryable<YB_Device>().Where(x => ids.Contains(x.Id)).ToList();
                   });
                   it.devname = allequ.FirstOrDefault(x => x.Id == it.equid)?.Name;
                   it.facecode = allequ.FirstOrDefault(x => x.Id == it.equid)?.FacCode;
                   var allbusiness = cache.Get(list =>
                   {
                       var ids = list.Select(x => x.Businesid).ToList().IDistinctList();
                       return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                   });
                   it.BusinessName = allbusiness.FirstOrDefault(x => x.Id == it.Businesid)?.Name;
                   it.Age = it.Month.TomAge();
                   it.createtime = it.createtime.ToYearDateTime();
                   var alluser = cache.Get(list =>
                   {
                       List<int> ids = list.Select(x => x.userid).ToList();
                       ids = ids.IDistinctList();
                       return dbClient.Queryable<YB_RegUser>().Where(x => ids.Contains(x.Id))
                       .Select(x => new YB_RegUser
                       {
                           Id = x.Id,
                           Headimg = x.Headimg,
                           Name = x.Name,
                           Phone = x.Phone
                       })
                       .ToList();
                   });

                   var allfamily = cache.Get(list =>
                   {
                       List<int> ids = list.Select(x => x.familyid).ToList();
                       ids = ids.IDistinctList();
                       return dbClient.Queryable<YB_Family>().Where(x => ids.Contains(x.Id)).ToList();
                   });

                   var user = alluser.FirstOrDefault(x => x.Id == it.userid);
                   var family = allfamily.FirstOrDefault(x => x.Id == it.familyid);
                   it.headimg = user != null ? user.Headimg : "";
                   if (family != null && family.IsSelf == 1)
                   {
                       it.nickname = $"{(user != null ? user.Name : "")}";
                   }
                   else
                   {
                       it.nickname = $"{(user != null ? user.Name : "")}({(family != null ? family.Name : "")})";
                   }
                   it.phone = user != null && isshowphone ? user.Phone : "";
                   if (currentUser.AccountType == AccountType.platform || isshowbodytype)
                   {
                       var allbodytype = cache.Get(list =>
                       {
                           var ids = list.Where(x => x.userid > 0).Select(x => x.userid).ToList();
                           return dbClient.Queryable<YB_LXBodyResult>().Where(x => ids.Contains(x.UserId)).ToList();
                       });
                       var results = allbodytype.Where(x => x.UserId == it.userid).ToList();
                       if (results != null && results.Count > 0)
                       {
                           var ids = results.Select(x => x.TypeId).ToList();
                           var guidlist = dbClient.Queryable<YB_LXBodyGuide>().Where(x => ids.Contains(x.TypeId)).ToList();
                           results.ForEach(x =>
                           {
                               var guild = guidlist.Where(e => e.TypeId == x.TypeId).FirstOrDefault();
                               if (guild != null)
                               {
                                   it.BodyType += $"{BodyType(x.BodyType, x.Result)},";
                               }
                           });
                           it.BodyType = it.BodyType.Substring(0, it.BodyType.Length - 1);
                       }
                   }
               })
               .ToPageListAsync(1, totalnum2, totalnum2);

            List<MeasureUserListDto> list1 = query2.ToList();
            List<MeasureUserListDto> list2 = new List<MeasureUserListDto>();

            if (param.queryParam.Any(s => s.Name.ToLower() == "name"))
            {
                var value = param.queryParam.Where(s => s.Name.ToLower() == "name").FirstOrDefault();
                if (value.Value.IsNullOrEmpty())
                {
                    list2 = list1.Skip((param.offset - 1) * param.limit).Take(param.limit).ToList();
                }
                else
                {
                    list1 = query2.Where(s => s.nickname.Contains(value.Value)).ToList();
                    list2 = list1.Skip((param.offset - 1) * param.limit).Take(param.limit).ToList();
                }
            }
            else
            {
                list2 = list1.Skip((param.offset - 1) * param.limit).Take(param.limit).ToList();
            }
            return new PageParms<MeasureUserListDto>
            {
                page = param.offset,
                Items = list2,
                totalnum = list1.Count,
                limit = param.limit
            };
        }

        private string BodyType(string type, int result)
            => (type, result) switch
            {
                _ when type == "平和质" && result == 2 => $"基本是{type}",
                _ when result == 1 => type,
                _ when result == 2 => $"倾向于{type}",
                _ => ""
            };

        /// <summary>
        /// 查询用户汇总数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<MeasureUserDto> GetUserData(int id)
        {
            var familydata = await dbClient.Queryable<YB_FamilyData>().FirstAsync(x => x.FamilyId == id);
            var data = new MeasureUserDto
            {
                FirstHeight = familydata.FirstHeight,
                FirstResultTime = familydata.FirstResultTime.HasValue ? familydata.FirstResultTime.Value.ToYearDateTime() : "-",
                FirstWeight = familydata.FirstWeight,
                LastHeight = familydata.LastHeight,
                LastResultTime = familydata.LastResultTime.HasValue ? familydata.LastResultTime.Value.ToYearDateTime() : "-",
                LastWeight = familydata.LastWeight,
                Weight = familydata.FirstWeight - familydata.LastWeight,
                Height = familydata.FirstHeight - familydata.LastHeight,
                TotalResultCnt = familydata.TotalCount,
                TodayResultCnt = familydata.TodayCount
            };
            return data;
        }

        /// <summary>
        /// 根据用户ID查询用户汇总汇总数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<FamilyDto>> GetUserDataByUserIdAsync(int id, QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var user = await dbClient.Queryable<YB_RegUser>().FirstAsync(x => x.Id == id);
            if (user == null)
            {
                return new PageParms<FamilyDto>
                {
                    page = param.offset,
                    Items = new List<FamilyDto>(),
                    totalnum = totalnum,
                    limit = param.limit
                };
            }
            var query = await dbClient.Queryable<YB_Family>()
                .Where(x => x.UserId == user.Id && x.Status != StatusType.Delete)
                .OrderBy(x => x.Createtime, OrderByType.Asc)
                .Select(x => new FamilyDto
                {
                    HeadImg = x.HeadImg,
                    Age = x.Age,
                    id = x.Id,
                    Sex = x.Sex,
                    IsSelf = x.IsSelf,
                    Type = x.Type,
                    Name = x.Name
                })
                .Mapper((it, cache) =>
                {
                    var alldata = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.id).ToList();
                        return dbClient.Queryable<YB_FamilyData>().Where(x => ids.Contains(x.FamilyId)).ToList();
                    });
                    var data = alldata.FirstOrDefault(x => x.FamilyId == it.id);
                    if (data != null)
                    {
                        it.FirstHeight = data.FirstHeight;
                        it.FirstResultTime = data.FirstResultTime.HasValue ? data.FirstResultTime.Value.ToYearDateTime() : "-";
                        it.FirstWeight = data.FirstWeight;
                        it.LastWeight = data.LastWeight;
                        it.LastResultTime = data.LastResultTime.HasValue ? data.LastResultTime.Value.ToYearDateTime() : "-";
                        it.Weight = Math.Abs(data.FirstWeight - data.LastWeight);
                        it.Height = Math.Abs(data.FirstHeight - data.LastHeight);
                        it.TotalResultCnt = data.TotalCount;
                        it.TodayResultCnt = data.TodayCount;
                    }
                    it.HeadImg = string.IsNullOrEmpty(it.HeadImg) ? DefaultService.HeadImg(it.Sex, it.Type) : it.HeadImg;
                })
                .ToPageListAsync(param.offset, param.limit, totalnum);
            ;
            return new PageParms<FamilyDto>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }

        /// <summary>
        /// 指定用户的体重记录列表
        /// </summary>
        /// <param name="id"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <returns></returns>
        public async Task<List<MeasureUserWeightDto>> GetUserResultAsync(int id, DateTime? starttime, DateTime? endtime)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = dbClient.Queryable<YB_nMeasureResult>().Where(x => SqlFunc.Subqueryable<YB_nUserResult>().Where(e => e.FamilyId == id && e.Id == x.Id).Any());
            if (!starttime.HasValue)
            {
                starttime = DateTime.Now.AddDays(-7).Date;
            }
            tempquery = tempquery.Where(x => x.createtime >= starttime.Value.Date);
            if (!endtime.HasValue)
            {
                endtime = DateTime.Now.AddDays(1).Date;
            }
            else
            {
                endtime = endtime.Value.AddDays(1).Date;
            }
            tempquery = tempquery.Where(x => x.createtime < endtime.Value);
            var list = await tempquery.OrderBy(x => x.createtime, OrderByType.Desc)
                .Select(x => new MeasureUserWeightDto
                {
                    weight = x.Weight,
                    time = SqlFunc.ToString(x.createtime)
                })
                .Mapper((it, cache) =>
                {
                    it.time = it.time.ToYearDateTime();
                })
                .ToListAsync();
            return list;
        }

        /// <summary>
        /// 根据用户ID查询用户测量记录
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<MeasureUserListDto>> GetUserResultByUserIdAsync(int userid, QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_nUserResult, YB_nResult, YB_nMeasureResult>((s, r, m) => new JoinQueryInfos(
                 JoinType.Left, s.Id == r.Id,
                  JoinType.Left, r.Id == m.Id
              )).Where((s, r, m) => s.UserId == userid);
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        if (x.Name == "createtime")
                        {
                            if (x.Type == 3)
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime >= SqlFunc.ToDate(x.Value));
                            }
                            else
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime <= SqlFunc.ToDate(x.Value));
                            }
                        }
                        else
                        {
                            conModels.Add(new ConditionalModel()
                            {
                                FieldName = x.Name,
                                ConditionalType = (ConditionalType)x.Type,
                                FieldValue = x.Value.Trim()
                            });
                        }
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            //if (currentUser.AccountType != (int)AccountType.platform)
            //{
            //    temquery = temquery.Where((r, m) => r.BusinessId == currentUser.BusinessId);
            //}
            if (currentUser.AccountType != AccountType.platform)
            {
                temquery = temquery.Where((s, r, m) => r.BusinessId == currentUser.BusinessId
                || SqlFunc.Subqueryable<YB_DeviceAlloc>().Where(e => e.EquId == r.EquId && (e.ToBusinessId == currentUser.BusinessId || e.FromBusinessId == currentUser.BusinessId)).Any()
                || SqlFunc.Subqueryable<YB_Device>().Where(e => e.Id == r.EquId && e.BindBusinessId == currentUser.BusinessId).Any()
                );
            }
            var query = await temquery.OrderBy((s, r, m) => r.CreateTime, OrderByType.Desc)
                 .Select((s, r, m) => new MeasureUserListDto
                 {
                     Month = m.Month,
                     sfr = m.sfr,
                     bmi = m.bmi,
                     fatlevel = m.fatlevel,
                     fat_r = m.fat_r,
                     fat_w = m.fat_w,
                     body = m.body,
                     bodyage = m.bodyage,
                     bone = m.bone,
                     cmi = m.cmi,
                     createtime = SqlFunc.ToString(r.CreateTime),
                     Height = r.Height,
                     kcal = m.kcal,
                     lbm = m.lbm,
                     id = r.Id,
                     muscle = m.muscle,
                     muscleval = m.muscleval,
                     protein = m.protein,
                     proteinval = m.proteinval,
                     visceral = m.visceral,
                     water = m.water,
                     weight = m.Weight,
                     userid = s.UserId,
                     familyid = s.FamilyId,
                     sex = m.Sex,
                     equid = r.EquId,
                     Businesid = r.BusinessId
                 })
                .Mapper((it, cache) =>
                {
                    var allequ = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.equid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Device>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.devname = allequ.FirstOrDefault(x => x.Id == it.equid)?.Name;
                    it.facecode = allequ.FirstOrDefault(x => x.Id == it.equid)?.FacCode;
                    var allbusiness = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.Businesid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.BusinessName = allbusiness.FirstOrDefault(x => x.Id == it.Businesid)?.Name;
                    it.Age = it.Month.TomAge();
                    it.createtime = it.createtime.ToYearDateTime();
                    var alluser = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.userid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_RegUser>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var allfamily = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.familyid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_Family>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    var allfans = cache.Get(list =>
                    {
                        var ids = list.Where(x => !string.IsNullOrEmpty(x.fansid)).Select(x => Guid.Parse(x.fansid)).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_WXFans>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var user = alluser.FirstOrDefault(x => x.Id == it.userid);
                    if (user == null && it.DevType == 2)
                    {
                        var fans = allfans.FirstOrDefault(x => x.Id.ToString().ToUpper() == it.fansid);
                        it.headimg = fans != null ? fans.HeadImgUrl : "";
                        it.nickname = fans != null ? fans.NickName : "";
                        it.sex = fans != null ? fans.Sex : 0;
                    }
                    else
                    {
                        var family = allfamily.FirstOrDefault(x => x.Id == it.familyid);
                        it.headimg = user != null ? user.Headimg : "";
                        if (family != null && family.IsSelf == 1)
                        {
                            it.nickname = $"{(user != null ? user.Name : "")}";
                        }
                        else
                        {
                            it.nickname = $"{(user != null ? user.Name : "")}({(family != null ? family.Name : "")})";
                        }
                    }
                    it.phone = user != null ? user.Phone : "";
                })
                .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<MeasureUserListDto>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }

        /// <summary>
        /// 导出信息
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResultInfo> ExportAsync(QueryParams param)
        {
            var temquery = dbClient.Queryable<YB_nUserResult, YB_nResult, YB_nMeasureResult>((s, r, m) => new JoinQueryInfos(
               JoinType.Left, s.Id == r.Id,
                JoinType.Left, r.Id == m.Id
            )).Where((s, r, m) => s.UserId > 0);
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        if (x.Name == "createtime")
                        {
                            if (x.Type == 3)
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime >= SqlFunc.ToDate(x.Value));
                            }
                            else
                            {
                                temquery = temquery.Where((s, r, m) => r.CreateTime <= SqlFunc.ToDate(x.Value));
                            }
                        }
                        else if (x.Name.ToLower() == "facecode")
                        {
                            temquery = temquery.Where((s, r, m) => SqlFunc.Subqueryable<YB_Device>().Where(e => e.FacCode == x.Value && e.Id == r.EquId).Any());
                        }
                        else if (x.Name.ToLower() == "devtype")
                        {
                            int type = x.Value.ToInt();
                            temquery = temquery.Where((s, r, m) => s.DevType == type);
                        }
                        else
                        {
                            conModels.Add(new ConditionalModel()
                            {
                                FieldName = x.Name,
                                ConditionalType = (ConditionalType)x.Type,
                                FieldValue = x.Value.Trim()
                            });
                        }
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            if (currentUser.AccountType != AccountType.platform)
            {
                temquery = temquery.Where((s, r, m) => r.BusinessId == currentUser.BusinessId
                || SqlFunc.Subqueryable<YB_DeviceAlloc>().Where(e => e.EquId == r.EquId && (e.ToBusinessId == currentUser.BusinessId || e.FromBusinessId == currentUser.BusinessId)).Any()
                || SqlFunc.Subqueryable<YB_Device>().Where(e => e.Id == r.EquId && e.BindBusinessId == currentUser.BusinessId).Any()
                );
            }
            var sheets = new List<Dictionary<string, object>>();
            bool isshowphone = currentUser.AccountType == AccountType.platform || BusinessShowConst.PhoneShowIds.Contains(currentUser.BusinessId);
            bool isshowbodytype = currentUser.AccountType == AccountType.platform || BusinessShowConst.BodyTypeShowIds.Contains(currentUser.BusinessId);
            var query = await temquery.OrderBy((s, r, m) => r.CreateTime, OrderByType.Desc)
                 .Select((s, r, m) => new MeasureUserListDto
                 {
                     Month = m.Month,
                     sfr = m.sfr,
                     bmi = m.bmi,
                     fatlevel = m.fatlevel,
                     fat_r = m.fat_r,
                     fat_w = m.fat_w,
                     body = m.body,
                     bodyage = m.bodyage,
                     bone = m.bone,
                     cmi = m.cmi,
                     createtime = SqlFunc.ToString(r.CreateTime),
                     Height = r.Height,
                     kcal = m.kcal,
                     lbm = m.lbm,
                     id = r.Id,
                     muscle = m.muscle,
                     muscleval = m.muscleval,
                     protein = m.protein,
                     proteinval = m.proteinval,
                     visceral = m.visceral,
                     water = m.water,
                     weight = m.Weight,
                     userid = s.UserId,
                     familyid = s.FamilyId,
                     sex = m.Sex,
                     equid = r.EquId,
                     Businesid = r.BusinessId,
                     DevType = s.DevType
                 })
                .Mapper((it, cache) =>
                {
                    var allequ = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.equid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Device>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.devname = allequ.FirstOrDefault(x => x.Id == it.equid)?.Name;
                    it.facecode = allequ.FirstOrDefault(x => x.Id == it.equid)?.FacCode;
                    var allbusiness = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.Businesid).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.BusinessName = allbusiness.FirstOrDefault(x => x.Id == it.Businesid)?.Name;
                    it.Age = it.Month.TomAge();
                    it.createtime = it.createtime.ToYearDateTime();
                    var alluser = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.userid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_RegUser>().Where(x => ids.Contains(x.Id))
                        .Select(x => new YB_RegUser
                        {
                            Id = x.Id,
                            Headimg = x.Headimg,
                            Name = x.Name,
                            Phone = x.Phone
                        })
                        .ToList();
                    });

                    var allfamily = cache.Get(list =>
                    {
                        List<int> ids = list.Select(x => x.familyid).ToList();
                        ids = ids.IDistinctList();
                        return dbClient.Queryable<YB_Family>().Where(x => ids.Contains(x.Id)).ToList();
                    });

                    var user = alluser.FirstOrDefault(x => x.Id == it.userid);
                    var family = allfamily.FirstOrDefault(x => x.Id == it.familyid);
                    it.headimg = user != null ? user.Headimg : "";
                    if (family != null && family.IsSelf == 1)
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}";
                    }
                    else
                    {
                        it.nickname = $"{(user != null ? user.Name : "")}({(family != null ? family.Name : "")})";
                    }
                    it.phone = user != null && isshowphone ? user.Phone : "";
                    if (isshowbodytype)
                    {
                        var allbodytype = cache.Get(list =>
                        {
                            var ids = list.Where(x => x.userid > 0).Select(x => x.userid).ToList();
                            return dbClient.Queryable<YB_LXBodyResult>().Where(x => ids.Contains(x.UserId)).ToList();
                        });
                        var results = allbodytype.Where(x => x.UserId == it.userid).ToList();
                        if (results != null && results.Count > 0)
                        {
                            var ids = results.Select(x => x.TypeId).ToList();
                            var guidlist = dbClient.Queryable<YB_LXBodyGuide>().Where(x => ids.Contains(x.TypeId)).ToList();
                            results.ForEach(x =>
                            {
                                var guild = guidlist.Where(e => e.TypeId == x.TypeId).FirstOrDefault();
                                if (guild != null)
                                {
                                    it.BodyType += $"{BodyType(x.BodyType, x.Result)},";
                                }
                            });
                            it.BodyType = it.BodyType.Substring(0, it.BodyType.Length - 1);
                        }
                    }
                    var dics = new Dictionary<string, object> { { "用户", it.nickname }, { "手机号", it.phone }, { "客户", it.BusinessName }, { "设备", it.devname }, { "设备序列号", it.facecode }, { "性别", it.sex == GenderType.Male ? "男" : (it.sex == GenderType.FeMale ? "女" : "未知") }, { "体重", it.weight }, { "身高", it.Height }, { "年龄", it.Age }, { "BMI", it.bmi }, { "脂肪率", it.fat_r }, { "体型", it.body }, { "体龄", it.bodyage }, { "骨重", it.bone }, { "分数", it.cmi }, { "脂肪量", it.fat_w }, { "等级", it.fatlevel }, { "基础代谢", it.kcal }, { "去脂体重", it.lbm }, { "肌肉率", it.muscle }, { "肌肉量", it.muscleval }, { "蛋白率", it.protein }, { "蛋白量", it.proteinval }, { "皮下脂肪", it.sfr }, { "内脂", it.visceral }, { "水份", it.water }, { "测量时间", it.createtime } };
                    if (!isshowphone)
                    {
                        dics.Remove("手机号");
                    }
                    sheets.Add(dics);
                })
                .ToListAsync();
            return await _excelService.ExportAsync(sheets);
        }
    }
}