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 Panda.DynamicWebApi.Attributes;


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>> GetInspectionList(GetDataInspectionDto dto)
        {
            //_repository.GetQueryable.GetQueryable < DataInspection >

            var trialData = await _repository.GetQueryable<Trial>().Where(x => x.Id == dto.TrialId).AsNoTracking().FirstOrDefaultAsync();


            trialData.TrialFinishTime = trialData.TrialFinishTime == null ? DateTime.Now : trialData.TrialFinishTime;

            #region 逻辑代码
            var query = from data in _repository.GetQueryable<DataInspection>()
                            //.Where(x => (x.TrialId == dto.TrialId)||(x.TrialId==null&&x.CreateTime>= trialData.CreateTime && x.CreateTime <= trialData.TrialFinishTime))


                        join trial in _repository.GetQueryable<Trial>().IgnoreQueryFilters() on data.TrialId equals trial.Id into trialtemp
                        from leftrial in trialtemp.DefaultIfEmpty()
                        join site in _repository.GetQueryable<Site>().IgnoreQueryFilters() on data.SiteId equals site.Id into sitetemp
                        from leftsite in sitetemp.DefaultIfEmpty()

                        join trialSite in _repository.GetQueryable<TrialSite>().IgnoreQueryFilters() on new { SiteId = leftsite.Id, Trialid = leftrial.Id } equals new { SiteId = trialSite.SiteId, Trialid = trialSite.TrialId } into trialSitetemp
                        from lefttrialSite in trialSitetemp.DefaultIfEmpty()


                        join subject in _repository.GetQueryable<Subject>().IgnoreQueryFilters() on data.SubjectId equals subject.Id into subtemp
                        from leftsubject in subtemp.DefaultIfEmpty()
                        join subjectVisit in _repository.GetQueryable<SubjectVisit>().IgnoreQueryFilters() 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>().IgnoreQueryFilters() on data.CreateUserId equals user.Id into usertemp
                        from leftuser in usertemp.DefaultIfEmpty()
                        join usertype in _repository.GetQueryable<UserType>().IgnoreQueryFilters() 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>().IgnoreQueryFilters() 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 && x.IsEnable == true) on
                            data.Identification.ToLower()
                         equals
                            leftfrontAuditConfig.Identification.ToLower()
                        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,
                            ModuleTypeId = leftmoduleTypec.Id,
                            BlindName = leftsubjectVisit.BlindName,
                            TrialId = data.TrialId,
                            SiteId = data.SiteId,
                            SubjectId = data.SubjectId,
                            SubjectVisitId = data.SubjectVisitId,
                            //OptType = data.OptType,
                            IP = data.IP,
                            Reason = data.Reason,
                            IsSign = leftfrontAuditConfig.IsHaveSign,
                            SignId = data.SignId,
                            ParentId = data.ParentId,
                            ChildrenTypeId = data.ChildrenTypeId,
                            //JsonDetail = data.JsonDetail,
                            //SiteName = data.SiteName,
                            //ExperimentName = data.TrialName,
                            //FirstName = leftsubject.FirstName,
                            //LastName = leftsubject.LastName,

                            Id = data.Id,
                            //ParentJson = leftparent.JsonDetail,
                            VisitName = leftsubjectVisit.VisitName,
                            SubjectVisitName = leftsubjectVisit.VisitName,


                            //CreateUserName = leftuser.UserName,
                            //RoleName = leftusertype.UserTypeShortName,

                            CreateUserRealName=data.CreateUserRealName,
                            CreateUserName = data.CreateUserName,
                            RoleName=data.RoleName,


                            //UserFirstName = leftuser.FirstName,
                            //UserLastName = leftuser.LastName,
                            ExperimentName = leftrial.ExperimentName,


                            SubjectCode = leftsubject.Code,
                            SiteCode = lefttrialSite.TrialSiteCode,

                            ResearchProgramNo = leftrial.ResearchProgramNo,
                            ObjectTypeId = data.ObjectTypeId,
                            Description = leftfrontAuditConfig.Description,
                            ModuleTypeName = leftmoduleTypec.ValueCN,
                            SignText = lefttrialSign.SignText,
                            Identification = leftfrontAuditConfig.Identification,
                            FrontAuditConfigId = leftfrontAuditConfig.Id,
                            ParentIdentification = leftparent.Identification,
                            OptTypeId = leftOptType.Id,
                            VisitNum = leftsubjectVisit.VisitNum,
                            InPlan = leftsubjectVisit.InPlan,
                            //IsFrontAdd=data.IsFrontAdd,
                            BatchId = data.BatchId,
                            OptType = leftOptType.Value,
                            ObjectRelationParentId = data.ObjectRelationParentId,
                            GeneralId = data.GeneralId
                        };

            query = query.WhereIf(dto.SiteId != null, x => x.SiteId == dto.SiteId)
                  //.WhereIf(dto.RelationDeadlineTime != null, x => x.CreateTime <= dto.RelationDeadlineTime.Value.AddSeconds(1))
                   .Where(x => (x.TrialId == dto.TrialId) || (x.TrialId == null && x.CreateTime >= trialData.CreateTime && x.CreateTime <= trialData.TrialFinishTime))

            #region 废弃
                   //   .WhereIf(dto.BatchId != null && dto.ObjectRelationParentId == null && dto.GeneralId == null, x => x.BatchId == dto.BatchId)
                   //  .WhereIf(dto.BatchId != null && dto.GeneralId != null && dto.ObjectRelationParentId == null, x => x.BatchId == dto.BatchId ||
                   //  ((x.GeneralId == dto.GeneralId || x.ObjectRelationParentId == dto.GeneralId) && x.CreateTime <= dto.RelationDeadlineTime.Value.AddSeconds(1)))
                   //  .WhereIf(dto.ObjectRelationParentId != null && dto.BatchId != null && dto.GeneralId != null,
                   //  x =>
                   //  x.BatchId == dto.BatchId ||      //同一事务批次
                   //  //x.ObjectRelationParentId == dto.ObjectRelationParentId || //不同对象 但是同一层级 适用于子对象


                   //((x.GeneralId == dto.ObjectRelationParentId || //子稽查 查询父记录
                   //  x.GeneralId == dto.GeneralId ||  //同一对象
                   //  x.ObjectRelationParentId == dto.GeneralId  //父稽查 查询子记录
                   //  ) && x.CreateTime <= dto.RelationDeadlineTime.Value.AddSeconds(1)))
            #endregion
                   .WhereIf(dto.BatchId != null, x => x.BatchId == dto.BatchId)
                   .WhereIf(dto.BatchId == null && dto.GeneralId != null, x => x.GeneralId == dto.GeneralId)


                 .WhereIf(!dto.SubjectInfo.IsNullOrEmpty(), x => x.SubjectCode.Contains(dto.SubjectInfo))
                 //.WhereIf(dto.VisitPlanInfo != null&& dto.VisitPlanInfo!=(decimal) 1.11, x => x.VisitNum == dto.VisitPlanInfo)
                 //.WhereIf(dto.VisitPlanInfo != (decimal)1.11,x=>x.InPlan!=null&& x.InPlan==false)
                 .WhereIf(dto.StartTime != null, x => x.CreateTime >= dto.StartTime)
                 .WhereIf(dto.EndTime != null, x => x.CreateTime <= dto.EndTime)
                 .WhereIf(dto.ModuleType != null, x => x.ModuleTypeId == 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

            if (dto.VisitPlanInfo != null && dto.VisitPlanInfo.Value != (decimal)1.11)
            {
                query = query.Where(x => x.VisitNum == dto.VisitPlanInfo.Value);
            }
            else if (dto.VisitPlanInfo != null)
            {
                query = query.Where(x => x.InPlan == false);
            }
            return await query.ToPagedListAsync(dto.PageIndex, dto.PageSize, dto.SortField.IsNullOrEmpty() ? nameof(GetDataInspectionOutDto.CreateTime) : dto.SortField, dto.Asc);
        }




        /// <summary>
        /// 传入参数记录ID
        /// </summary>
        /// <param name="SignInfo"></param>
        /// <returns></returns>
        public async Task<Guid> RecordSing(SignDTO SignInfo)
        {
            if (SignInfo != null)
            {
                var verifyResult = await VerifySignatureAsync(SignInfo);
                var signId = await AddSignRecordAsync(SignInfo);
                _userInfo.SignId = signId;
                return signId;
            }
            else
            {
                return default(Guid);
            }

        }

        /// <summary>
        /// 完成签名
        /// </summary>
        /// <param name="signId"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public async Task CompletedSign(Guid signId, IResponseOutput response)
        {
            if (response.IsSuccess)
            {
                await _repository.BatchUpdateAsync<TrialSign>(t => t.Id == signId, u => new TrialSign() { IsCompleted = true });
            }
        }



        /// <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("用户名或密码错误");
            }
            else if (user.Status == UserStateEnum.Disable)
            {
                throw new BusinessValidationFailedException("当前用户已被禁用。");
            }
            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;

        }


    }
}