using Castle.Core.Internal;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Panda.DynamicWebApi.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IRaCIS.Core.Application.Service.Inspection
{
    [NonDynamicWebApi]
    public class InspectionService : BaseService, IInspectionService
    {
        private readonly IRepository<DataInspection> _dataInspectionRepository;
        private readonly IRepository<FrontAuditConfig> _frontAuditConfigRepository;

        public InspectionService(IRepository<DataInspection> dataInspectionRepository,
            IRepository<FrontAuditConfig> frontAuditConfigRepository
            )
        {
            this._dataInspectionRepository = dataInspectionRepository;
            this._frontAuditConfigRepository = frontAuditConfigRepository;
        }

      

        public async Task<PageOutput<GetDataInspectionOutDto>> GetInspectionData(GetDataInspectionDto dto)
        {
            //_repository.GetQueryable.GetQueryable < DataInspection >

            #region 逻辑代码
            var query = from data in _repository.GetQueryable<DataInspection>()
                        join trial in _repository.GetQueryable<Trial>() on data.TrialId equals trial.Id into trialtemp
                        from leftrial in trialtemp.DefaultIfEmpty()
                        join site in _repository.GetQueryable<Site>() on data.SiteId equals site.Id into sitetemp
                        from leftsite in sitetemp.DefaultIfEmpty()
                        join subject in _repository.GetQueryable<Subject>() on data.SubjectId equals subject.Id into subtemp
                        from leftsubject in subtemp.DefaultIfEmpty()
                        join subjectVisit in _repository.GetQueryable<SubjectVisit>() on data.SubjectVisitId equals subjectVisit.Id into subjectVisittemp
                        from leftsubjectVisit in subjectVisittemp.DefaultIfEmpty()
                        join parent in _repository.GetQueryable<DataInspection>() on data.ParentId equals parent.Id into parenttemp
                        from leftparent in parenttemp.DefaultIfEmpty()
                        join user in _repository.GetQueryable<User>() on data.CreateUserId equals user.Id into usertemp
                        from leftuser in usertemp.DefaultIfEmpty()
                        join usertype in _repository.GetQueryable<UserType>() on leftuser.UserTypeId equals usertype.Id into usertypetemp
                        from leftusertype in usertypetemp.DefaultIfEmpty()







                            //join moduleTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ModuleType") on 1 equals 1
                            //join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = moduleTyped.Id, ModuleType = data.ModuleType } equals new { ParentId = moduleTypec.ParentId.Value, ModuleType = moduleTypec.Value } into moduleTypectemp

                            //join childrenTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ChildrenType") on 1 equals 1
                            //join childrenTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = childrenTyped.Id, ModuleType = data.ChildrenType } equals new { ParentId = childrenTypec.ParentId.Value, ModuleType = childrenTypec.Value } into childrenTypectemp
                            //from leftchildrenTypec in childrenTypectemp.DefaultIfEmpty()

                            //join ObjectTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "ObjectType") on 1 equals 1
                            //join ObjectTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = ObjectTyped.Id, ModuleType = data.ObjectType } equals new { ParentId = ObjectTypec.ParentId.Value, ModuleType = ObjectTypec.Value } into objectTypetemp
                            //from leftObjectType in objectTypetemp.DefaultIfEmpty()

                            //join OptTyped in _repository.GetQueryable<Dictionary>().Where(x => x.Code == "OptType") on 1 equals 1
                            //join OptTypec in _repository.GetQueryable<Dictionary>() on new { ParentId = OptTyped.Id, ModuleType = data.OptType } equals new { ParentId = OptTypec.ParentId.Value, ModuleType = OptTypec.Value } into optTypetemp
                            //from leftOptType in optTypetemp.DefaultIfEmpty()


                        join trialSign in _repository.GetQueryable<TrialSign>() on data.SignId equals trialSign.Id into trialSigntemp
                        from lefttrialSign in trialSigntemp.DefaultIfEmpty()


                        join leftfrontAuditConfig in _repository.GetQueryable<FrontAuditConfig>().Where(x=>x.ConfigType=="M"&&x.Identification!=null) on new
                        {
                            data.Identification
                        } equals new
                        {
                            leftfrontAuditConfig.Identification,

                        } 



                        join moduleTypec in _repository.GetQueryable<Dictionary>() on new { ModuleType = leftfrontAuditConfig.ModuleTypeId.Value } equals new { ModuleType = moduleTypec.Id } into moduleTypectemp
                        from leftmoduleTypec in moduleTypectemp.DefaultIfEmpty()


                      
                        join OptTypec in _repository.GetQueryable<Dictionary>() on new { ModuleType = leftfrontAuditConfig.OptTypeId.Value } equals new { ModuleType = OptTypec.Id } into optTypetemp
                        from leftOptType in optTypetemp.DefaultIfEmpty()

                        select new GetDataInspectionOutDto()
                        {
                            CreateTime = data.CreateTime,
                            CreateUserId = data.CreateUserId,
                            ModuleType = leftmoduleTypec.Id,
                            BlindName = data.BlindName,
                            TrialId = data.TrialId,
                            SiteId = data.SiteId,
                            SubjectId = data.SubjectId,
                            SubjectVisitId = data.SubjectVisitId,
                            //OptType = data.OptType,
                            IP = data.IP,
                            Reason = data.Reason,
                            IsSign = data.IsSign,
                            SignId = data.SignId,
                            ParentId = data.ParentId,
                            ChildrenType = data.ChildrenType,
                            JsonDetail = data.JsonDetail,
                            SiteName = data.SiteName,
                            ExperimentName = data.TrialName,
                            FirstName = leftsubject.FirstName,
                            LastName = leftsubject.LastName,
                            Id = data.Id,
                            ParentJson = leftparent.JsonDetail,
                            VisitName = data.SubjectVisitName,
                            CreateUser = leftuser.UserName,
                            UserFirstName = leftuser.FirstName,
                            UserLastName = leftuser.LastName,
                            //SubjectCode=leftsubject.Code,
                            SubjectCode =leftsubject.Code,
                            SubjectVisitName=leftsubjectVisit.VisitName,
                            CreateUserName = leftuser.FirstName + leftuser.LastName,
                            RoleName= leftusertype.UserTypeShortName,
                            TrialName= leftrial.ExperimentName,
                            SiteCode=leftsite.SiteCode,
                            ResearchProgramNo= leftrial.ResearchProgramNo,
                            ObjectType=data.ObjectType,
                            Description=leftfrontAuditConfig.Description,
                            ModuleTypeName= leftmoduleTypec.ValueCN,
                            SignText= lefttrialSign.SignText,
                            Identification= leftfrontAuditConfig.Identification,
                            ParentIdentification = leftparent.Identification,
                            OptType = leftOptType.Id,
                            VisitNum=leftsubjectVisit.VisitNum,
                            IsFrontAdd=data.IsFrontAdd,
                            OptTypeName = leftOptType.Value,

                        };

            query = query.WhereIf(dto.TrialId != null, x => x.TrialId == dto.TrialId)
                 .WhereIf(dto.SiteId != null, x => x.SiteId == dto.SiteId)
                 .WhereIf(!dto.SubjectInfo.IsNullOrEmpty(), x => x.SubjectCode.Contains(dto.SubjectInfo))
                 .WhereIf(dto.VisitPlanInfo != null, x => x.VisitNum == dto.VisitPlanInfo)
                 .WhereIf(dto.StartTime != null, x => x.CreateTime >= dto.StartTime)
                 .WhereIf(dto.EndTime != null, x => x.CreateTime <= dto.EndTime)
                 .WhereIf(dto.ModuleType!=null, x => x.ModuleType == dto.ModuleType)
                 .WhereIf(!dto.Description.IsNullOrEmpty(), x => x.Description == dto.Description)
                 .WhereIf(!dto.OpByUserName.IsNullOrEmpty(), x => x.CreateUserName.Contains(dto.OpByUserName))
                 //.WhereIf(!dto.SubjectInfo.IsNullOrEmpty(), x => x.SubjectCode.Contains(dto.SubjectInfo))
                 .WhereIf(dto.IsSign != null, x => x.IsSign == dto.IsSign);


            #endregion



            dto.Asc = false;
            return await query.ToPagedListAsync(dto.PageIndex, dto.PageSize, "CreateTime", dto.Asc);
        }

        //public async Task<string> 
     

        /// <summary>
        /// 通用逻辑封装
        /// </summary>
        /// <param name="OptCommand">方法参数</param>
        /// <param name="AuditInfo">添加稽查</param>
        /// <param name="SignInfo">用户签名</param>
        /// <param name="fun">委托</param>
        /// <param name="response">方法返回的结果</param>
        /// <returns></returns>
        public async Task<dynamic> Enforcement(dynamic OptCommand, DataInspectionAddDTO AuditInfo, SignDTO SignInfo, dynamic fun, IResponseOutput? response=null)
        {

          

            if (response != null && response.IsSuccess == false)
            {
                return response;
            }
            Guid? signId = null;
            MapData(OptCommand, AuditInfo);
            if (AuditInfo.IsSign)
            {
                // 验证用户签名信息
                var verifyResult = await VerifySignatureAsync(SignInfo);
                signId = await AddSignRecordAsync(SignInfo);
                if (verifyResult.IsSuccess == false)
                {
                    return verifyResult;
                }
                //await AddSignRecordAsync(SignInfo);
            }

            IResponseOutput bResult;

            if (response != null)
            {
                bResult = response;
            }
            else
            {
                bResult = await fun(OptCommand);
            }

            // 用户 签名某个文档  
            if (bResult.IsSuccess == false)
            {
                return bResult;
            }

            if (AuditInfo.IsSign)
            {
                var signSuccess = await _repository.BatchUpdateAsync<TrialSign>(t => t.Id == signId, u => new TrialSign() { IsCompleted = true });
            }

            //// 判断是否需要前面
            //if (AuditInfo.NeedSava)
            //{
            //    await AddInspectionRecordAsync(AuditInfo, signId);
            //}

            return bResult;
        }


        /// <summary>
        ///  映射 SiteId  SubjectId  SubjectVisitId  TrialId  最开始没有  需要特殊处理
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mapData"></param>
        public void MapData(dynamic data, dynamic mapData)
        {
            List<string> column = new List<string>() { "TrialId", "SiteId", "SubjectId", "SubjectVisitId" };
            foreach (var item in column)
            {
                try
                {
                    var i = mapData.GetType().GetProperty(item).GetValue(mapData);
                    if (i == null)
                    {
                        var value = data.GetType().GetProperty(item).GetValue(data);
                        mapData.GetType().GetProperty(item).SetValue(mapData, value);
                    }
                  
                }
                catch (Exception)
                {
                    continue;

                }
            }
        }

        /// <summary> 验证用户签名信息 </summary> ///  
        public async Task<IResponseOutput> VerifySignatureAsync(SignDTO signDTO)
        {
            var user = await _repository.FirstOrDefaultAsync<User>(u => u.UserName == signDTO.UserName && u.Password == signDTO.PassWord);
            if (user == null)
            {
                throw new BusinessValidationFailedException("password error");
            }
            else if (user.Status == UserStateEnum.Disable)
            {
                throw new BusinessValidationFailedException("The user has been disabled!");
            }
            return ResponseOutput.Ok();

        }

        /// <summary> 添加签名记录 </summary> ///  
        public async Task<Guid> AddSignRecordAsync(SignDTO signDTO)
        {
            var add = await _repository.AddAsync(_mapper.Map<TrialSign>(signDTO));

            var success = await _repository.SaveChangesAsync();

            return add.Id;

        }

        /// <summary>
        /// 添加稽查记录
        /// </summary>
        /// <param name="addDto">添加对象</param>
        /// <param name="signId">签名Id</param>
        /// <returns></returns>
        public async Task<IResponseOutput> AddInspectionRecordAsync(DataInspectionAddDTO addDto, Guid? signId = null)
        {
            if (addDto == new DataInspectionAddDTO())
            {
                return ResponseOutput.Ok();
            }
            //await SetEnum(addDto);
            var add = _mapper.Map<DataInspection>(addDto);
            await SetInspectionNameValue(add);
            Guid? parentId = null;
            parentId = (await _repository.GetQueryable<DataInspection>().Where(x => x.TrialId == add.TrialId && x.SubjectVisitId == add.SubjectVisitId && x.SubjectId == add.SubjectId && x.SiteId == add.SiteId && x.ChildrenType == add.ChildrenType && x.ObjectType == add.ObjectType && x.VisitStageId == add.VisitStageId && x.GeneralId == add.GeneralId).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync())?.Id;
            add.ParentId = parentId;

            if (add.CreateTime == default(DateTime))
            {
                add.CreateTime = DateTime.Now;
            }
           
            add.CreateUserId = _userInfo.Id;
            add.SignId = signId;
            add.IP = _userInfo.IP;


            add =await _dataInspectionRepository.SetDataInspectionDateType(add);


            //await _repository.AddAsync(add);


            //var success = await _repository.SaveChangesAsync();
            return ResponseOutput.Ok();

        }

     

        /// <summary>
        /// 批量添加稽查记录
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        public async Task AddListInspectionRecordAsync(List<DataInspection> datas)
        {
            //var trialIds= datas.Select(x=>x.TrialId).Distinct().ToList();
            //var subjectVisitIds= datas.Select(x=>x.SubjectVisitId).Distinct().ToList();
            //var subjectIds = datas.Select(x => x.SubjectId).Distinct().ToList();
            //var siteIds = datas.Select(x => x.SiteId).Distinct().ToList();
            //var childrenTypes= datas.Select(x => x.ChildrenType).Distinct().ToList();
            //var objectTypes = datas.Select(x => x.ObjectType).Distinct().ToList();


            await _dataInspectionRepository.AddListInspectionRecordAsync(datas);

            await _dataInspectionRepository.SaveChangesAsync();

            //foreach (var add in datas)
            //{
            //    await SetInspectionNameValue(add);
            //    add.ParentId = (await _repository.GetQueryable<DataInspection>().Where(x => x.TrialId == add.TrialId && x.SubjectVisitId == add.SubjectVisitId && x.SubjectId == add.SubjectId && x.SiteId == add.SiteId && x.ChildrenType == add.ChildrenType && x.ObjectType == add.ObjectType&&x.VisitStageId==add.VisitStageId&& x.GeneralId == add.GeneralId).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync())?.Id;
            //    add.CreateUserId = _userInfo.Id;
            //    add.IP = _userInfo.IP;


            //    var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(add.JsonDetail);

            //    foreach (var item in JsonData.Keys)
            //    {
            //        if (JsonData[item].ToString().ToLower() == "true".ToLower())
            //        {
            //            JsonData[item] = "是";
            //        } else if (JsonData[item].ToString().ToLower() == "false".ToLower())
            //        {
            //            JsonData[item] = "否";
            //        }

            //    }
            //    add.JsonDetail= JsonConvert.SerializeObject(JsonData);
            //}

            //await _dataInspectionRepository.AddRangeAsync(datas);

        }

        /// <summary>
        /// 往json里面添加属性
        /// </summary>
        /// <param name="json">json</param>
        /// <param name="keyValues">字典</param>
        /// <returns></returns>
        public string AddJsonItem(string json, Dictionary<string,object> keyValues)
        {
          
            var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(json);

            foreach (var item in keyValues)
            {
                if (JsonData.ContainsKey(item.Key))
                {
                    JsonData[item.Key] = item.Value;
                }
                else {
                    JsonData.Add(item.Key, item.Value);
                }
              
            }
            return JsonConvert.SerializeObject(JsonData);

        }

        ///// <summary>
        ///// 处理枚举
        ///// </summary>
        ///// <returns></returns>
        //public async Task SetEnum(DataInspectionAddDTO Data)
        //{
        //    //Data.JsonDetail= await _dataInspectionRepository.SetEnum(Data.TrialId.Value, Data.Identification, Data.JsonDetail);
        //    #region 枚举
        //    //try
        //    //{
        //    //    var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(Data.JsonDetail);
        //    //    foreach (var item in Data.EnumList)
        //    //    {
        //    //        if (!JsonData.ContainsKey(item.Key))
        //    //        {
        //    //            continue;
        //    //        }
        //    //        var value = JsonData[item.Key];
        //    //        if (value.GetType() == typeof(JArray))
        //    //        {
        //    //            JArray arrays = (JArray)value;
        //    //            if (item.Type.ToLower() == "id".ToLower())
        //    //            {
        //    //                List<Guid> guids = new List<Guid>();
        //    //                arrays.ForEach(x =>
        //    //                {
        //    //                    guids.Add(Guid.Parse(x.ToString()));
        //    //                });
        //    //                JsonData[item.Key] = string.Join(',', await _repository.GetQueryable<Dictionary>().Where(x => guids.Contains(x.Id)).Select(x => x.ValueCN).ToListAsync());
        //    //            }
        //    //            else if (item.Type.ToLower() == "ChildGroup".ToLower())
        //    //            {
        //    //                List<string> guids = new List<string>();
        //    //                arrays.ForEach(x =>
        //    //                {
        //    //                    guids.Add(x.ToString());
        //    //                });
        //    //                JsonData[item.Key] = string.Join(',', await
        //    //                    _repository.GetQueryable<Dictionary>().Where(x => x.Code == item.Code).GroupJoin(
        //    //                         _repository.GetQueryable<Dictionary>().Where(x => guids.Contains(x.ChildGroup)), a => a.Id, b => b.ParentId, (a, b) => new
        //    //                         {
        //    //                             parent = b
        //    //                         }).SelectMany(a => a.parent, (m, n) => new
        //    //                         {
        //    //                             value = n.ValueCN
        //    //                         }).Select(x => x.value).ToListAsync()
        //    //                        );
        //    //            }
        //    //            else
        //    //            {
        //    //                List<string> guids =new List<string>();
        //    //                arrays.ForEach(x =>
        //    //                {
        //    //                    guids.Add(x.ToString());
        //    //                });
        //    //                JsonData[item.Key] = string.Join(',', await
        //    //                    _repository.GetQueryable<Dictionary>().Where(x => x.Code == item.Code).GroupJoin(
        //    //                         _repository.GetQueryable<Dictionary>().Where(x=>guids.Contains(x.Code)), a => a.Id, b => b.ParentId, (a, b) => new
        //    //                         {
        //    //                             parent = b
        //    //                         }).SelectMany(a => a.parent, (m, n) => new
        //    //                         {
        //    //                             value = n.ValueCN
        //    //                         }).Select(x => x.value).ToListAsync()
        //    //                        );
        //    //            }
        //    //        }
        //    //        else
        //    //        {
        //    //            if (item.Type.ToLower() == "id".ToLower())
        //    //            {
        //    //                Guid guid = Guid.Parse(value.ToString());
        //    //                JsonData[item.Key] = await _repository.GetQueryable<Dictionary>().Where(x => guid == x.Id).Select(x => x.ValueCN).FirstOrDefaultAsync();
        //    //            }
        //    //            else if (item.Type.ToLower() == "ChildGroup".ToLower())
        //    //            {
        //    //                JsonData[item.Key] = await _repository.GetQueryable<Dictionary>().Where(x => x.Code == item.Code).Join(_repository.GetQueryable<Dictionary>().Where(x => x.ChildGroup == value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
        //    //                {
        //    //                    value = b.ValueCN
        //    //                }).Select(x => x.value).FirstOrDefaultAsync();
        //    //            }
        //    //            else
        //    //            {
        //    //                JsonData[item.Key] = await _repository.GetQueryable<Dictionary>().Where(x=>x.Code==item.Code).Join(_repository.GetQueryable<Dictionary>().Where(x=>x.Code== value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
        //    //                {
        //    //                   value=b.ValueCN
        //    //                }).Select(x=>x.value).FirstOrDefaultAsync();

        //    //            }
        //    //        }
        //    //    }

              
           
        //    //    Data.JsonDetail = JsonConvert.SerializeObject(JsonData);
              
        //    //}
        //    //catch (Exception)
        //    //{

        //    //    throw new BusinessValidationFailedException("Json 对象枚举异常");
        //    //}
        


        //    #endregion
        //}


        /// <summary>
        /// 设置项目以及名称
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public async Task SetInspectionNameValue(DataInspection Data)
        {

            await _dataInspectionRepository.SetInspectionNameValue(Data);

            //#region 项目名称

            //var trialdata = await _repository.GetQueryable<Trial>().FirstOrDefaultAsync(x => x.Id == Data.TrialId);
            //Data.ResearchProgramNo = trialdata?.ResearchProgramNo;
            //if (Data.TrialName.IsNullOrEmpty())
            //{
            //    Data.TrialName = trialdata?.ExperimentName;
            //}
            //#endregion

            //#region 测试中心名称


            //Data.SiteCode = (await _repository.GetQueryable<TrialSite>().FirstOrDefaultAsync(x => x.TrialId == Data.TrialId && x.SiteId == Data.SiteId))?.TrialSiteCode;

            //var sitedata = await _repository.GetQueryable<Site>().FirstOrDefaultAsync(x => x.Id == Data.SiteId);

            //if (Data.SiteName.IsNullOrEmpty())
            //{
            //    Data.SiteName = sitedata?.SiteName;
            //}
            //#endregion

            //#region 受试者


            //if (Data.SubjectCode.IsNullOrEmpty())
            //{

            //    Data.SubjectCode = (await _repository.GetQueryable<Subject>().FirstOrDefaultAsync(x => x.Id == Data.SubjectId))?.Code;
            //}
            //#endregion

            //#region 访视
            //if (Data.SubjectVisitName.IsNullOrEmpty())
            //{
            //    Data.SubjectVisitName = (await _repository.GetQueryable<SubjectVisit>().FirstOrDefaultAsync(x => x.Id == Data.SubjectVisitId))?.VisitName;
            //}
            //#endregion

            //#region 创建者
            //if (Data.CreateUserName.IsNullOrEmpty() || Data.RoleName.IsNullOrEmpty())
            //{
            //    var userdata = await _repository.GetQueryable<User>().Where(x => x.Id == Data.CreateUserId).GroupJoin(_repository.GetQueryable<UserType>(), a => a.UserTypeId, b => b.Id, (a, b) => new
            //    {
            //        UserName = a.FirstName + a.LastName,
            //        Role = b
            //    }).SelectMany(a => a.Role, (m, n) => new
            //    {
            //        UserName = m.UserName,
            //        RoleName = n.UserTypeShortName
            //    }).FirstOrDefaultAsync();

            //    if (userdata != null)
            //    {
            //        if (Data.CreateUserName.IsNullOrEmpty())
            //        {
            //            Data.CreateUserName = userdata?.UserName;
            //        }


            //        if (Data.RoleName.IsNullOrEmpty())
            //        {
            //            Data.RoleName = userdata?.RoleName;
            //        }
            //    }
            //}
            //#endregion

            //#region 取操作类型
            //try
            //{
            //    var from = await _frontAuditConfigRepository.FirstOrDefaultAsync(x => x.Identification == Data.Identification);
            //    Data.ObjectType = from.ObjectTypeId;
            //    Data.OptType = from.OptTypeId;
            //    Data.ChildrenType = from.ChildrenTypeId;
            //    Data.ModuleType = from.ModuleTypeId;
            //}
            //catch (Exception)
            //{

            //    throw new BusinessValidationFailedException("操作标识异常");
            //}
        

            //#endregion

        }
     
    
    }
}
