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 YBDevice.CommonService.DevTypeInfo;
using YBDevice.Entity;
using YBDevice.NApi.Application.BusinessClient.AccountInfo;

namespace YBDevice.NApi.Application.BusinessClient.MeasureInfo
{
    /// <summary>
    /// 测量记录
    /// </summary>
    public class ResultService : BaseApiInfoService, IResultService, ITransient
    {
        private readonly ISqlSugarRepository<YB_nMeasureResult> repository;
        private readonly SqlSugarClient dbClient;
        private readonly IDeviceTypeService _deviceTypeService;
        public ResultService(ISqlSugarRepository<YB_nMeasureResult> sqlSugarRepository, IDeviceTypeService deviceTypeService)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            _deviceTypeService = deviceTypeService;
        }
        /// <summary>
        /// 测量记录列表
        /// </summary>
        /// <param name="queryParams"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetListAsync(BusinessResultC2SDto queryParams)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = 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 (queryParams.DevType > 0)
            {
                var types = await _deviceTypeService.GetDevTypesAsync(queryParams.DevType);
                tempquery = tempquery.Where((s, r, m) => types.Contains(s.DevType));
            }
            if (!string.IsNullOrWhiteSpace(queryParams.Phone))
            {
                tempquery = tempquery.Where((s, r, m) => SqlFunc.Subqueryable<YB_RegUser>().Where(x => x.Phone == queryParams.Phone && x.Id == s.UserId).Any());
            }
            tempquery = tempquery.Where((s, r, m) => r.BusinessId == CurrentBusinessId
                || SqlFunc.Subqueryable<YB_DeviceAlloc>().Where(e => e.EquId == r.EquId && (e.ToBusinessId == CurrentBusinessId || e.FromBusinessId == CurrentBusinessId)).Any()
                || SqlFunc.Subqueryable<YB_Device>().Where(e => e.Id == r.EquId && e.BindBusinessId == CurrentBusinessId).Any()
                );
            var query = await tempquery.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 = r.Weight,
                    userid = s.UserId,
                    familyid = s.FamilyId,
                    sex = m.Sex,
                    equid = r.EquId,
                    Age = SqlFunc.ToString(m.Age),
                    BusinessId = r.BusinessId
                })
                .Mapper((it, cache) =>
                {
                    var allbusiness = cache.Get(list =>
                    {
                        var ids = list.Where(x => x.BusinessId > 0).Select(x => x.BusinessId).ToList().IDistinctList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.BusinessName = allbusiness.FirstOrDefault(x => x.Id == it.BusinessId)?.Name;

                    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;
                    it.Age = $"{it.Age}岁";
                    // 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.Type == (int)ResultType.Five)
                    {
                        var fans = allfans.FirstOrDefault(x => x.Id.ToString().ToUpper() == it.fansid);
                        it.headimg = fans != null ? fans.HeadImgUrl : "";
                        it.nickname = fans != null ? fans.NickName : "";
                    }
                    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(queryParams.offset, queryParams.limit, totalnum);
            var result = new PageParms<MeasureUserListDto>
            {
                page = queryParams.offset,
                Items = query,
                totalnum = totalnum,
                limit = queryParams.limit
            };
            return new ResultInfo(ResultState.SUCCESS, "success", result);
        }
        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<ResultInfo> GetUserData(Guid id)
        {
            var measure = await dbClient.Queryable<YB_nUserResult>().FirstAsync(x => x.Id == id);
            if (measure == null)
            {
                return new ResultInfo(ResultState.FAIL, "暂无数据");
            }
            YB_FamilyData familydata;

            var familyrealdata = await dbClient.Queryable<YB_FamilyRealData>().FirstAsync(x => x.FamilyId == measure.FamilyId && x.DevType == measure.DevType);
            if (familyrealdata != null)
            {
                familydata = new YB_FamilyData
                {
                    FirstHeight = familyrealdata.FirstHeight,
                    FirstResultTime = familyrealdata.FirstResultTime,
                    FirstWeight = familyrealdata.FirstWeight,
                    LastHeight = familyrealdata.LastHeight,
                    LastResultTime = familyrealdata.LastResultTime,
                    LastWeight = familyrealdata.LastWeight,
                    TotalCount = familyrealdata.TotalCount,
                    TodayCount = familyrealdata.TodayCount
                };
            }
            else
            {
                familydata = await dbClient.Queryable<YB_FamilyData>().FirstAsync(x => x.FamilyId == measure.FamilyId);
            }
            if (familydata == null)
            {
                return new ResultInfo(ResultState.FAIL, "暂无数据");
            }
            int day = 0;
            if (familydata.FirstResultTime.HasValue)
            {
                day = (DateTime.Now.Date - familydata.FirstResultTime.Value.Date).TotalDays.ToInt();
            }
            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 = Math.Abs(familydata.FirstWeight - familydata.LastWeight),
                Height = Math.Abs(familydata.FirstHeight - familydata.LastHeight),
                TotalResultCnt = familydata.TotalCount,
                TodayResultCnt = familydata.TodayCount,
                Day = day
            };
            return new ResultInfo(ResultState.SUCCESS, "success", data);
        }
        /// <summary>
        /// 测量记录详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetUserResultDetailAsync(Guid id)
        {
            var result = await dbClient.Queryable<YB_nMeasureResult>().FirstAsync(x => x.Id == id);
            var data = new MeasureDto();
            if (result == null)
            {
                //只显示体重这些信息
                var res = await dbClient.Queryable<YB_nResult>().FirstAsync(x => x.Id == id);
                if (res != null)
                {
                    data.weight = res.Weight;
                    data.Height = res.Height;
                    data.bmi = (res.Weight / (res.Height * res.Height)).ToDecimal(1);
                    data.createtime = res.CreateTime.ToYearDateTime();
                    return new ResultInfo(ResultState.SUCCESS, "success", data);
                }
                return new ResultInfo(ResultState.FAIL, "记录未找到");
            }
            string type = string.Empty;
            //只有丽秀显示
            if (CurrentBusinessId == 14)
            {
                var userid = await dbClient.Queryable<YB_nUserResult>().Where(x => x.Id == id).Select(x => x.UserId).FirstAsync();
                var results = await dbClient.Queryable<YB_LXBodyResult>().Where(x => x.UserId == userid).ToListAsync();
                if (results != null && results.Count > 0)
                {
                    var ids = results.Select(x => x.TypeId).ToList();
                    var guidlist = await dbClient.Queryable<YB_LXBodyGuide>().Where(x => ids.Contains(x.TypeId)).ToListAsync();
                    results.ForEach(x =>
                    {
                        var guild = guidlist.Where(e => e.TypeId == x.TypeId).FirstOrDefault();
                        if (guild != null)
                        {
                            type += $"{BodyType(x.BodyType, x.Result)},";
                        }
                    });
                    type = type.Substring(0, type.Length - 1);
                }
            }
            data = new MeasureDto
            {
                weight = result.Weight,
                createtime = result.createtime.ToYearDateTime(),
                sfr = result.sfr,
                Age = result.Age.ToString(),
                bmi = result.bmi,
                body = result.body,
                bodyage = result.bodyage,
                bone = result.bone,
                cmi = result.cmi,
                fatlevel = result.fatlevel,
                fat_r = result.fat_r,
                fat_w = result.fat_w,
                Height = result.Height,
                kcal = result.kcal,
                lbm = result.lbm,
                muscle = result.muscle,
                muscleval = result.muscleval,
                protein = result.protein,
                proteinval = result.proteinval,
                visceral = result.visceral,
                water = result.water,
                BodyType = type
            };
            return new ResultInfo(ResultState.SUCCESS, "success", data);
        }

        /// <summary>
        /// 查询用户所有测量项记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="queryParams"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetUserResultListAsync(Guid id, QueryParams queryParams)
        {
            RefAsync<int> totalnum = 0;
            var result = await dbClient.Queryable<YB_nUserResult>().FirstAsync(x => x.Id == id);
            if (result == null)
            {
                return new ResultInfo(ResultState.FAIL, "记录未找到");
            }
            var tempquery = dbClient.Queryable<YB_nMeasureResult>().Where(x => SqlFunc.Subqueryable<YB_nUserResult>().Where(e => e.Id == x.Id && e.FamilyId == result.FamilyId).Any());
            if (queryParams.queryParam != null && queryParams.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                queryParams.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    tempquery = tempquery.Where(conModels);
                }
            }
            var list = await tempquery.OrderBy(x => x.createtime, OrderByType.Desc)
                .Select(x => new MeasureDto
                {
                    weight = x.Weight,
                    createtime = SqlFunc.ToString(x.createtime),
                    sfr = x.sfr,
                    Age = SqlFunc.ToString(x.Age),
                    bmi = x.bmi,
                    body = x.body,
                    bodyage = x.bodyage,
                    bone = x.bone,
                    cmi = x.cmi,
                    fatlevel = x.fatlevel,
                    fat_r = x.fat_r,
                    fat_w = x.fat_w,
                    Height = x.Height,
                    kcal = x.kcal,
                    lbm = x.lbm,
                    muscle = x.muscle,
                    muscleval = x.muscleval,
                    protein = x.protein,
                    proteinval = x.proteinval,
                    visceral = x.visceral,
                    water = x.water
                })
                .Mapper((it, cache) =>
                {
                    it.createtime = it.createtime.ToYearDateTime();
                })
              .ToPageListAsync(queryParams.offset, queryParams.limit, totalnum);
            var results = new PageParms<MeasureDto>
            {
                page = queryParams.offset,
                Items = list,
                totalnum = totalnum,
                limit = queryParams.limit
            };
            return new ResultInfo(ResultState.SUCCESS, "success", results);
        }

        /// <summary>
        /// 查询用户体重记录
        /// </summary>
        /// <param name="measureUserQuerDto"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetUserWeightListAsync(MeasureUserQueryDto measureUserQuerDto)
        {
            var result = await dbClient.Queryable<YB_nUserResult>().FirstAsync(x => x.Id == measureUserQuerDto.id);
            if (result == null)
            {
                return new ResultInfo(ResultState.FAIL, "记录未找到");
            }
            var tempquery = dbClient.Queryable<YB_nMeasureResult>().Where(x => SqlFunc.Subqueryable<YB_nUserResult>().Where(e => e.Id == x.Id && e.FamilyId == result.FamilyId).Any());
            if (!string.IsNullOrEmpty(measureUserQuerDto.starttime))
            {
                DateTime time = measureUserQuerDto.starttime.ToDate();
                tempquery = tempquery.Where(x => x.createtime >= time);
            }
            if (!string.IsNullOrEmpty(measureUserQuerDto.endtime))
            {
                DateTime time = measureUserQuerDto.endtime.ToDate();
                tempquery = tempquery.Where(x => x.createtime < time);
            }
            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 new ResultInfo(ResultState.SUCCESS, "success", list);
        }
    }
}
