using AutoMapper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Domain.Share;
using Newtonsoft.Json;
using MediatR;
using System.Linq.Expressions;
using System.Text;

namespace IRaCIS.Core.Application.MediatR.Handlers
{
    public class ConsistencyVerificationHandler : IRequestHandler<ConsistencyVerificationRequest, string>
    {
        private readonly IRepository<DicomStudy> _studyRepository;
        private readonly IUserInfo _userInfo;
        private readonly IRepository<Subject> _subjectRepository;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<TrialSite> _trialSiteRepository;
        private readonly IMapper _mapper;
        private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;

        /// <summary>
        /// 构造函数注入
        /// </summary>

        public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
            IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
            IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
            IMapper mapper)
        {
            _noneDicomStudyRepository = noneDicomStudyRepository;
            _studyRepository = studyRepository;
            _userInfo = userInfo;
            _subjectRepository = subjectRepository;
            _subjectVisitRepository = subjectVisitRepository;
            _trialSiteRepository = trialSiteRepository;
            _mapper = mapper;
        }

        async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken)
        {
            var trialId = request.TrialId;

            //处理Excel大小写
            request.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
            var etcList = request.ETCList;

            //Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId;

            //subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));

            Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == request.TrialId &&
            (x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));

            var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
                             join trialSite in _trialSiteRepository.Where(t => t.TrialId == trialId) on sv.SiteId equals trialSite.SiteId
                             join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
                             join study in _studyRepository.AsQueryable() on sv.Id equals study.SubjectVisitId
                             select new CheckDBModel()
                             {
                                 SubjectVisitId = sv.Id,
                                 SiteCode = trialSite.TrialSiteCode,
                                 StudyDate = study.StudyTime == null ? string.Empty : ((DateTime)study.StudyTime).ToString("yyyy-MM-dd"),
                                 StudyId = study.Id,
                                 Modality = study.ModalityForEdit,
                                 SubjectCode = subject.Code,
                                 VisitName = sv.VisitName,
                             };

            var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
                                join trialSite in _trialSiteRepository.Where(t => t.TrialId == trialId) on sv.SiteId equals trialSite.SiteId
                                join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
                                join noneDicomStudy in _noneDicomStudyRepository.AsQueryable() on sv.Id equals noneDicomStudy.SubjectVisitId
                                select new CheckDBModel()
                                {
                                    SubjectVisitId = sv.Id,
                                    SiteCode = trialSite.TrialSiteCode,
                                    StudyDate = noneDicomStudy.ImageDate.ToString("yyyy-MM-dd"),
                                    StudyId = noneDicomStudy.Id,
                                    Modality = noneDicomStudy.Modality,
                                    SubjectCode = subject.Code,
                                    VisitName = sv.VisitName,
                                };

            var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();

            //处理数据库 大小写
            dbList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });

            var dbCheckList = _mapper.Map<List<CheckViewModel>>(dbList);

            ////按照数据库数据检查批次分组   按照数据库的数据 一个个的检查批次对比 
            //var svGroup = dbList.GroupBy(t => new { t.SubjectVisitId, t.SiteCode, t.SubjectCode, t.VisitName })
            //       .Select(g => new { g.Key.SubjectCode, g.Key.VisitName, g.Key.SiteCode, g.Key.SubjectVisitId, StudyList = g.ToList() }).ToList();

            //按照Excel数据检查批次分组   按照数据库的数据 一个个的检查批次对比 
            var svExcelGroup = etcList.GroupBy(t => new { t.SiteCode, t.SubjectCode, t.VisitName })
                   .Select(g => new { g.Key.SubjectCode, g.Key.VisitName, g.Key.SiteCode, ExcelStudyList = g.ToList() }).ToList();


            foreach (var sv in svExcelGroup)
            {

                //Excel 的数据 在IRC 中可以找到该检查批次
                if (dbCheckList.Any(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName))
                {

                    var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();

                    //找到etc 当前visit  site  和subject 一致的检查列表
                    var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();



                    StringBuilder dialogMsg = new StringBuilder();
                    dialogMsg.Append("您好,根据本系统自动识别，该患者当前检查批次在IRC系统中已提交的影像检查情况如下：");
                    var num = 0;
                    List<ParamInfoDto> paramInfoList = new List<ParamInfoDto>();
                    foreach (var item in dbVisitStudyList)
                    {
                        num++;
                        dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查");
                        paramInfoList.Add(new ParamInfoDto()
                        {
                            Modality = item.Modality,
                            StudyDate = item.StudyDate,
                        });
                    }

                    var subjectVisitId = dbVisitStudyList.FirstOrDefault().SubjectVisitId;
                    var dbSV = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();

                    #region 更换核对的顺序 以Excel 数据为准 注释
                    //// 该检查批次 在EDC Excel中没有任何数据
                    //if (etcVisitStudyList.Count == 0)
                    //{
                    //    dialogMsg.AppendLine($"<br/>");
                    //    dialogMsg.AppendLine($"<br><span style='color: #f00'>存在问题如下：</span>");
                    //    num = 0;
                    //    foreach (var item in sv.StudyList)
                    //    {
                    //        num++;
                    //        dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(EDC 缺少) ");
                    //    }

                    //    dialogMsg.AppendLine($"<br/>");
                    //    dialogMsg.AppendLine(@$"<br>说明：为高效解决/处理以上全部质疑问题，麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致，部分检查（如PET -CT)可能同时存在多种模态影像。准确核实后，请回复该检查批次正确的影像检查情况。");

                    //    dbSV.CheckResult = "当前检查批次在EDC表中未找到数据,请核对 SubjectCode、 SiteCode 、VisitName 是否和EDC系统保持一致";
                    //    dbSV.CheckState = CheckStateEnum.CVIng;
                    //    dbSV.ForwardState = ForwardStateEnum.ToForward;
                    //    dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply;
                    //    dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
                    //    {
                    //        SubjectVisitId = sv.SubjectVisitId,
                    //        IsCRCNeedReply = true,
                    //        TalkContent = dialogMsg.ToString(),
                    //        ParamInfo = JsonConvert.SerializeObject(paramInfoList),
                    //        UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
                    //        CreateTime = DateTime.Now
                    //    });
                    //}
                    //else
                    #endregion

                    {
                        //etc 和数据库 并集
                        var unionList = dbVisitStudyList.Union(etcVisitStudyList);
                        // 数据库存在
                        var dbExceptExcel = dbVisitStudyList.Except(etcVisitStudyList);

                        // excel 存在
                        var excelExceptDB = etcVisitStudyList.Except(dbCheckList);

                        //ETC 和系统的完全一致    两者没有差别
                        if (dbExceptExcel.Count() == 0 && excelExceptDB.Count() == 0)
                        {
                            dialogMsg.AppendLine($"<br/>");
                            dialogMsg.AppendLine($"核对EDC数据，完全一致, 审核通过");


                            // dialogMsg.AppendLine(@$"<br>说明：为高效解决/处理以上全部质疑问题，麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致，部分检查（如PET -CT)可能同时存在多种模态影像。准确核实后，请回复该检查批次正确的影像检查情况。");
                            dbSV.CheckState = CheckStateEnum.CVPassed;
                            dbSV.CheckUserId = _userInfo.Id;
                            dbSV.CheckPassedTime = DateTime.Now;
                            dbSV.CheckResult = "核对EDC数据，完全一致";
                            dbSV.ManualPassReason = "自动核查通过";

                            //维护状态
                            dbSV.ReadingStatus = ReadingStatusEnum.TaskAllocate;

                            dbSV.RequestBackState = dbSV.RequestBackState == RequestBackStateEnum.CRC_RequestBack ? RequestBackStateEnum.PM_NotAgree : RequestBackStateEnum.NotRequest;
                            dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
                            {
                                SubjectVisitId = subjectVisitId,
                                ParamInfo = JsonConvert.SerializeObject(paramInfoList),
                                TalkContent = dialogMsg.ToString(),
                                UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
                                CreateTime = DateTime.Now
                            });
                        }
                        // ETC  和系统的有区别
                        else
                        {
                            dialogMsg.AppendLine($"<br/>");
                            dialogMsg.AppendLine($"<br><span style='color: #f00'>存在问题如下：</span>");

                            num = 0;
                            foreach (var item in dbExceptExcel)
                            {
                                num++;
                                dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(EDC 缺少) ");
                            }

                            foreach (var item in excelExceptDB)
                            {
                                num++;
                                dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(IRC 缺少) ");
                            }

                            dialogMsg.AppendLine($"<br/>");
                            dialogMsg.AppendLine(@$"<br>说明：为高效解决/处理以上全部质疑问题，麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致，部分检查（如PET -CT)可能同时存在多种模态影像。准确核实后，请回复该检查批次正确的影像检查情况。");

                            dbSV.CheckResult = "根据导入的一致性核查数据，请确认本检查批次以下不一致检查项信息：" + String.Join(" | ", dbExceptExcel.Select(t => $"EDC 缺少：{t.StudyDate} {t.Modality} ")) + "  |  "
                              + String.Join(" | ", excelExceptDB.Select(t => $"IRC 缺少:{t.StudyDate} {t.Modality}"));
                            //新增一致性核查质疑记录


                            dbSV.CheckState = CheckStateEnum.CVIng;
                            dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply;

                            //讲核查结果发送消息给IC
                            dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
                            {
                                SubjectVisitId = subjectVisitId,
                                IsCRCNeedReply = true,
                                TalkContent = dialogMsg.ToString(),
                                ParamInfo = JsonConvert.SerializeObject(paramInfoList),
                                UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
                                CreateTime = DateTime.Now
                            });
                        }

                    }
                    dbSV.CheckTime = DateTime.Now;
                }














            }
            await _subjectVisitRepository.SaveChangesAsync();
            return "OK";

        }

    }


}
