using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Service.Reading.Dto;
using MassTransit;
using IRaCIS.Core.Infra.EFCore.Common;
using Panda.DynamicWebApi.Attributes;
using AutoMapper;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Infrastructure;
using Newtonsoft.Json;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Application.Filter;

namespace IRaCIS.Application.Services
{
  
    /// <summary>
    /// 全局阅片
    /// </summary>
    public partial class ReadingImageTaskService : BaseService, IReadingImageTaskService
    {
        /// <summary>
        /// 提交全局阅片结果
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        //[NonDynamicMethod]
        public async Task<IResponseOutput> SubmitGlobalReadingInfo(SubmitGlobalReadingInfoInDto inDto)
        {
            //var result = await this.SaveGlobalReadingInfo(inDto);
            await VerifyTaskIsSign(inDto.GlobalTaskId);
            await this.SubmitTaskChangeState(inDto.GlobalTaskId);

            return ResponseOutput.Ok(true);
        }


        /// <summary>
        /// 批量提交全局阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> BatchSubmitGlobalReadingInfo(BatchSubmitGlobalReadingInfo inDto)
        {
            await VerifyTaskIsSign(inDto.GlobalTaskId);

            var criterionType = await _visitTaskRepository.Where(x => x.Id == inDto.GlobalTaskId).Select(x => x.TrialReadingCriterion.CriterionType).FirstNotNullAsync();
            foreach (var item in inDto.VisitTaskAnswerList)
            {
                foreach (var answer in item.AnswerList)
                {
                    await _readingGlobalTaskInfoRepository.BatchDeleteNoTrackingAsync(x => x.GlobalTaskId == inDto.GlobalTaskId && x.TaskId == item.VisitTaskId && x.GlobalAnswerType == answer.GlobalAnswerType && x.QuestionId == answer.QuestionId);


                    if (criterionType == CriterionType.PCWG3)
                    {
                        await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == answer.QuestionId
                   && x.Answer != answer.Answer && answer.Answer != string.Empty && answer.Answer != null
                   , x => new ReadingTaskQuestionAnswer()
                   {
                       Answer= answer.Answer,
                       GlobalChangeAnswer = answer.Answer,
                       IsGlobalChange = true,
                   });
                    }
                    else
                    {
                        await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == answer.QuestionId
                   && x.Answer != answer.Answer && answer.Answer != string.Empty && answer.Answer != null
                   , x => new ReadingTaskQuestionAnswer()
                   {
                       GlobalChangeAnswer = answer.Answer,
                       IsGlobalChange = true,
                   });
                    }
                   
                }
            }
           var answers=  inDto.VisitTaskAnswerList.SelectMany(x => x.AnswerList.Select(y => new ReadingGlobalTaskInfo()
            {
                Answer = y.Answer,
                QuestionId = y.QuestionId,
                SubjectId = inDto.SubjectId,
                GlobalTaskId = inDto.GlobalTaskId,
                GlobalAnswerType = y.GlobalAnswerType,
                TaskId = x.VisitTaskId,
                TrialId = inDto.TrialId,
            })).ToList();

            await _readingGlobalTaskInfoRepository.AddRangeAsync(answers);
            await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });
            var result = await _readingGlobalTaskInfoRepository.SaveChangesAsync();
            return ResponseOutput.Ok(result);
        }


        #region 全局阅片相关
        /// <summary>
        /// 保存全局阅片结果
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SaveGlobalReadingInfo(SaveGlobalReadingInfoInDto inDto)
        {
            await VerifyTaskIsSign(inDto.GlobalTaskId);
            var visitTaskId = inDto.QuestionList.Select(x => x.VisitTaskId).FirstOrDefault();

            foreach (var item in inDto.QuestionList)
            {

                await _readingGlobalTaskInfoRepository.BatchDeleteNoTrackingAsync(x => x.GlobalTaskId == inDto.GlobalTaskId && x.TaskId == visitTaskId && x.GlobalAnswerType == item.GlobalAnswerType && x.QuestionId == item.QuestionId);

                await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == item.QuestionId
                   && x.Answer != item.Answer && item.Answer != string.Empty && item.Answer != null
                   , x => new ReadingTaskQuestionAnswer()
                   {
                       GlobalChangeAnswer = item.Answer,
                       IsGlobalChange = true,
                   });
            }

            await _readingGlobalTaskInfoRepository.AddRangeAsync(inDto.QuestionList.Select(x => new ReadingGlobalTaskInfo()
            {
                Answer = x.Answer,
                QuestionId = x.QuestionId,
                SubjectId = inDto.SubjectId,
                GlobalTaskId = inDto.GlobalTaskId,
                GlobalAnswerType = x.GlobalAnswerType,
                TaskId = x.VisitTaskId,
                TrialId = inDto.TrialId,
            }).ToList());

            await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });

            var result = await _readingGlobalTaskInfoRepository.SaveChangesAsync();
            return ResponseOutput.Ok(result);

        }


        /// <summary>
        /// 获取全局阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetGlobalReadingInfoOutDto> GetGlobalReadingInfo(GetGlobalReadingInfoInDto inDto)
        {
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x=>x.Subject).FirstNotNullAsync();
            if (taskInfo.ReadingCategory != ReadingCategory.Global)
            {
                throw new BusinessValidationFailedException(_localizer["ReadingGlobal_NotGlobal"]);
            }
            GetGlobalReadingInfoOutDto result = new GetGlobalReadingInfoOutDto()
            {
                GlobalTaskId = inDto.VisitTaskId,
                ReadingTaskState = taskInfo.ReadingTaskState,

            };
            result.OtherGlobalTaskId = await _visitTaskRepository.Where(x => x.SouceReadModuleId == taskInfo.SouceReadModuleId && x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
              && x.IsSelfAnalysis == taskInfo.IsSelfAnalysis && x.TaskState == TaskState.Effect && x.DoctorUserId != taskInfo.DoctorUserId
            ).Select(x => x.Id).FirstOrDefaultAsync();

            result.TaskBlindName = taskInfo.TaskBlindName;
            if (taskInfo.IsAnalysisCreate)
            {
                result.SubjectCode = taskInfo.BlindSubjectCode;

            }
            else
            {
                result.SubjectCode = taskInfo.Subject.Code;
            }

          var judgeInfo  = await _visitTaskRepository.Where(x =>
                           x.SubjectId == taskInfo.SubjectId
                         && x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
                         && x.TaskState == TaskState.Effect
                         && x.ArmEnum == taskInfo.ArmEnum
                         && x.ReadingCategory == ReadingCategory.Judge
                        && x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
                        && x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
                        && x.DoctorUserId == taskInfo.DoctorUserId
                        && x.ReadingTaskState == ReadingTaskState.HaveSigned
                        && x.VisitTaskNum == taskInfo.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge]
                        && x.ReReadingApplyState != ReReadingApplyState.Agree).FirstOrDefaultAsync();
            if (judgeInfo != null)
            {
                result.JudgeTaskId = judgeInfo.Id;
                result.JudgeTaskName = judgeInfo.TaskBlindName;
            }


            // 一致性分析按照doctorId 其他按照分组


            var queruTask =  _visitTaskRepository.Where(x =>
                   x.TrialId == taskInfo.TrialId &&
                   x.SubjectId == taskInfo.SubjectId &&
                   x.ReadingCategory == ReadingCategory.Visit &&
                   x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
                   x.ReadingTaskState == ReadingTaskState.HaveSigned &&
                   x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
                   x.ArmEnum == taskInfo.ArmEnum &&
                   x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
                   x.DoctorUserId == taskInfo.DoctorUserId &&
                   x.TaskState == TaskState.Effect &&
                   x.VisitTaskNum < taskInfo.VisitTaskNum);


            if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
            {
                queruTask = _visitTaskRepository.Where(x => taskInfo.RelatedVisitTaskIdList.Contains(x.Id));
            }

            result.TaskList = await queruTask
                .OrderBy(x => x.VisitTaskNum).Select(x => new GlobalVisitInfo()
                {
                    VisitName = x.TaskName,
                    BlindName = x.TaskBlindName,
                    VisitTaskId = x.Id,
                    ArmEnum = taskInfo.ArmEnum,
                    VisitNum = x.SourceSubjectVisit.VisitNum,
                    IsBaseLine=x.SourceSubjectVisit.IsBaseLine,
                    VisitId = x.SourceSubjectVisitId.Value,
                   
                    BeforeQuestionList = x.ReadingTaskQuestionAnswerList.Where(y => y.ReadingQuestionTrial.GlobalReadingShowType!=GlobalReadingShowType.NotShow).OrderBy(y => y.ReadingQuestionTrial.ShowOrder)
                  .Select(y => new GlobalQuestionInfo()
                  {
                     
                      QuestionId = y.ReadingQuestionTrialId,
                      QuestionName = y.ReadingQuestionTrial.QuestionName.LanguageName(y.ReadingQuestionTrial.QuestionEnName, _userInfo.IsEn_Us),
                      AnswerGroup = y.ReadingQuestionTrial.AnswerGroup,
                      QuestionType = y.ReadingQuestionTrial.QuestionType,
                      LimitEdit= y.ReadingQuestionTrial.LimitEdit,
                      MaxAnswerLength=y.ReadingQuestionTrial.MaxAnswerLength,
                      FileType=y.ReadingQuestionTrial.FileType,
                      QuestionGenre = y.ReadingQuestionTrial.QuestionGenre,
                      DictionaryCode = y.ReadingQuestionTrial.DictionaryCode,
                      GlobalReadingShowType=y.ReadingQuestionTrial.GlobalReadingShowType,
                      AnswerCombination = y.ReadingQuestionTrial.AnswerCombination,
                      JudgeType = y.ReadingQuestionTrial.JudgeType,
                      Type = y.ReadingQuestionTrial.Type,
                      TypeValue = y.ReadingQuestionTrial.TypeValue,
                      ValueType = y.ReadingQuestionTrial.ValueType,
                      IsJudgeQuestion =y.ReadingQuestionTrial.IsJudgeQuestion,
                      Answer =y.Answer,
                  }).ToList()
                }).ToListAsync();



            var globalReadingQuestion = await _readingGlobalTaskInfoRepository.Where(x => x.GlobalTaskId == inDto.VisitTaskId).ToListAsync();
            var criterionType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();

            // Before的Answer取自于 上一次全局阅片的结果, 如果没有上一次全局阅片的结果  取检查批次的答案

            var lastGlobalTask = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Global &&
         x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
              x.SubjectId == taskInfo.SubjectId && x.IsAnalysisCreate == taskInfo.IsAnalysisCreate && x.TaskState == TaskState.Effect && x.VisitTaskNum < taskInfo.VisitTaskNum)
             .Where(x => x.DoctorUserId == taskInfo.DoctorUserId)
             .OrderByDescending(x=>x.VisitTaskNum)
             .FirstOrDefaultAsync();

            List<ReadingGlobalTaskInfo>? globalAnswers = new List<ReadingGlobalTaskInfo>();
            if (lastGlobalTask != null)
            {
                globalAnswers = await _readingGlobalTaskInfoRepository.Where(x => x.GlobalTaskId == lastGlobalTask.Id).ToListAsync();
            }

            if (criterionType != CriterionType.PCWG3)
            {
                result.TaskList.ForEach(x =>
                {

                    x.BeforeQuestionList.ForEach(y =>
                    {

                        var globalAnswer = globalAnswers.Where(z => z.QuestionId == y.QuestionId&&z.TaskId==x.VisitTaskId).Select(z => z.Answer).FirstOrDefault();
                        if (!globalAnswer.IsNullOrEmpty())
                        {
                            y.Answer = globalAnswer;
                            y.IsGlobalAnswer = true;
                        }
                       
                    });
                });
            }

            result.TaskList.ForEach(x =>
            {
                x.AfterQuestionList = x.BeforeQuestionList.Where(x=>x.IsJudgeQuestion).GroupJoin(
                    globalReadingQuestion
                      , l => new { a = l.QuestionId, b = x.VisitTaskId }
                      , r => new { a = r.QuestionId, b = r.TaskId }
                      , (l, r) => new { question = l, global = r })
                  .SelectMany(lr => lr.global.DefaultIfEmpty(), (lr, r) => new GlobalQuestionInfo
                  {
                      Answer = lr.global == null || lr.global.Count() == 0 ?
                      (inDto.UsingOriginalData ? lr.question.Answer : string.Empty) :
                      (lr.global.Select(x => x.Answer).FirstOrDefault().IsNullOrEmpty() && inDto.UsingOriginalData ?
                      lr.question.Answer : lr.global.Select(x => x.Answer).FirstOrDefault()
                      ),
                      VisitAnswer = lr.question.Answer,
                      IsHaveChange = lr.global.Any(x=>x.QuestionId!=null&&!x.Answer.IsNullOrEmpty()) ? true : false,
                      QuestionId = lr.question.QuestionId,
                      QuestionName = lr.question.QuestionName,
                      QuestionType = lr.question.QuestionType,
                      LimitEdit=lr.question.LimitEdit,
                      MaxAnswerLength=lr.question.MaxAnswerLength,
                      FileType=lr.question.FileType,
                      QuestionGenre = lr.question.QuestionGenre,
                      DictionaryCode = lr.question.DictionaryCode,
                      GlobalReadingShowType = lr.question.GlobalReadingShowType,
                      Type = lr.question.Type,
                      GlobalAnswerType = GlobalAnswerType.Question,
                      AnswerGroup = lr.question.AnswerGroup,
                      AnswerCombination = lr.question.AnswerCombination,
                      IsJudgeQuestion=lr.question.IsJudgeQuestion,
                      JudgeType = lr.question.JudgeType,
                      TypeValue = lr.question.TypeValue,
                      ValueType= lr.question.ValueType,

                  }).ToList();


                List<GetGlobalQuestionType> questionTypes = new List<GetGlobalQuestionType>()
                {
                };
                if (criterionType != CriterionType.PCWG3)
                {
                    var agreeOrNotAnswer = globalReadingQuestion.Where(y => y.TaskId == x.VisitTaskId && y.GlobalAnswerType == GlobalAnswerType.AgreeOrNot).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;

                    if (agreeOrNotAnswer.IsNullOrEmpty()&& lastGlobalTask!=null&& lastGlobalTask.RelatedVisitTaskIdList.Contains(x.VisitTaskId))
                    {
                        agreeOrNotAnswer = "1";
                    }

                    x.AgreeOrNot = new List<GlobalQuestionInfo>()
                   {
                       new GlobalQuestionInfo()
                       {
                           Answer = agreeOrNotAnswer,
                           QuestionName = "",
                           Type = "input",
                           GlobalAnswerType=GlobalAnswerType.AgreeOrNot,
                           GlobalReadingShowType= GlobalReadingShowType.AllShow,
                       }
                   
                   };

                    questionTypes.Add(new GetGlobalQuestionType() { GlobalAnswerType = GlobalAnswerType.UpdateType, QuestionName = "评估更新类型" });
                }
                else
                {
                    x.AgreeOrNot = new List<GlobalQuestionInfo>() { };
                }




             
               
                questionTypes.Add(new GetGlobalQuestionType() { GlobalAnswerType = GlobalAnswerType.Reason, QuestionName = "全局阅片备注" });
                foreach (var item in questionTypes)
                {
                    x.AfterQuestionList.Add(new GlobalQuestionInfo()
                    {
                        Answer = globalReadingQuestion.Where(y => y.TaskId == x.VisitTaskId && y.GlobalAnswerType == item.GlobalAnswerType).Select(x => x.Answer).FirstOrDefault() ?? string.Empty,
                        QuestionName = item.QuestionName,
                        Type = "input",
                        GlobalAnswerType = item.GlobalAnswerType,
                        GlobalReadingShowType= GlobalReadingShowType.AllShow,

                    });
                }



            });

            if (criterionType == CriterionType.PCWG3)
            {


                // 找到上一个全局阅片

           
              
                result.TaskList.ForEach(x =>
                {
                    foreach (var item in x.AfterQuestionList.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation))
                    {
                        var answer = item.Answer;

                        var globalanswer = globalAnswers.Where(y => y.TaskId == x.VisitTaskId && y.QuestionId == item.QuestionId).FirstOrDefault();

                        if (globalanswer != null)
                        {
                            answer = globalanswer.Answer;
                        }
                        else
                        {
                            answer = x.BeforeQuestionList.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
                        }

                        if (item.Answer.IsNullOrEmpty())
                        {
                            item.Answer = answer;
                        }

                        item.VisitAnswer = answer;

                    }


                    // 在修改前 去除这个问题
                    x.BeforeQuestionList = x.BeforeQuestionList.Where(x => x.QuestionType != QuestionType.SiteVisitForTumorEvaluation).ToList();

                });
            }



            var subjectVisitId = await _readModuleRepository.Where(x => x.Id == taskInfo.SouceReadModuleId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync();
            var isBaseLine = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
            List<CriterionDictionaryInfo> assessTypeList = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == taskInfo.TrialReadingCriterionId
          && x.ParentCode == ReadingCommon.CriterionDictionary.GlobalAssess
          )
               //.WhereIf(isBaseLine,x=>x.IsBaseLineUse)
               //.WhereIf(!isBaseLine,x=>x.IsFollowVisitUse)
          .Select(x => new CriterionDictionaryInfo()
          {
              Id = x.Id,
              DictionaryId = x.DictionaryId,
              ChildGroup = x.Dictionary.ChildGroup,
              IsBaseLineUse=x.IsBaseLineUse,
              IsFollowVisitUse=x.IsFollowVisitUse,
              Code = x.Dictionary.Code,
              Description = x.Dictionary.Description,
              ShowOrder = x.Dictionary.ShowOrder,
              ParentCode = x.Dictionary.Parent.Code,
              Value = x.Dictionary.Value,
              ValueCN = x.Dictionary.ValueCN
          }).OrderBy(x => x.ParentCode).ThenBy(x => x.ShowOrder).ToListAsync();
            result.AssessTypeList = assessTypeList;
            return result;
        }
        #endregion
    }
}
