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
    {
        #region 肿瘤学阅片相关

        /// <summary>
        /// 获取肿瘤学任务信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        [HttpPost]
        public async Task<GetOncologyReadingInfoOutDto> GetOncologyReadingInfo(GetOncologyReadingInfoInDto inDto)
        {
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();

            if (taskInfo.ReadingCategory != ReadingCategory.Oncology)
            {
                throw new BusinessValidationFailedException(_localizer["ReadingOncology_TaskError"]);
            }

            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).FirstOrDefaultAsync();


            GetOncologyReadingInfoOutDto result = new GetOncologyReadingInfoOutDto()
            {
                //TrialEvaluationResult = trialCriterion.EvaluationResult,
                IsShowDetail = trialCriterion.IsShowDetail,
                TrialEvaluationReason = trialCriterion.EvaluationReason.IsNullOrEmpty() ? ReadingCommon.EvaluationReason : trialCriterion.EvaluationReason,
                OncologyTaskId = inDto.VisitTaskId,
                ReadingTaskState = taskInfo.ReadingTaskState,
            };

            // 先找到是R1还是R2的阅片 先找到全局阅片

            var globalTaskInfo = await _visitTaskRepository
                .Where(x => x.SubjectId == taskInfo.SubjectId &&
                x.TaskState == TaskState.Effect &&
                x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
                x.ReadingCategory == ReadingCategory.Global &&
                x.VisitTaskNum < taskInfo.VisitTaskNum
                ).OrderByDescending(x => x.VisitTaskNum)
                .FirstNotNullAsync();


            // 最后取哪组的数据
            VisitTask visitTask = new VisitTask();

            // 判断是否产生裁判

            if (globalTaskInfo.JudgeVisitTaskId == null)
            {
                visitTask = globalTaskInfo;
            }
            else
            {
                var judgeResultTaskId = await _visitTaskRepository.Where(x => x.Id == globalTaskInfo.JudgeVisitTaskId).Select(x => x.JudgeResultTaskId).FirstOrDefaultAsync();
                if (judgeResultTaskId == null)
                {
                    throw new BusinessValidationFailedException(_localizer["ReadingOncology_Abnormal"]);
                }
                visitTask = await _visitTaskRepository.Where(x => x.Id == judgeResultTaskId).FirstOrDefaultAsync();
            }

            result.GlobalTaskId = visitTask.Id;
            result.SubjectId = visitTask.SubjectId;

            // 获取全局阅片信息
            var globalTaskReadingInfo = await this.GetGlobalReadingInfo(new GetGlobalReadingInfoInDto()
            {
                UsingOriginalData = true,
                VisitTaskId = visitTask.Id
            });


            // 找到对应的访视
            List<OncologyVisitTaskInfo> oncologyVisits = await _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)
                .OrderBy(x => x.VisitTaskNum).Select(x => new OncologyVisitTaskInfo()
                {
                    VisitName = x.SourceSubjectVisit.VisitName,
                    VisitTaskId = x.Id,
                    //  QuestionList = x.ReadingTaskQuestionAnswerList.Where(y => y.ReadingQuestionTrial.IsJudgeQuestion).OrderBy(y => y.ReadingQuestionTrial.ShowOrder)
                    //.Select(y => new OncologyQuestion()
                    //{
                    //    QuestionId = y.ReadingQuestionTrialId,
                    //    QuestionName = y.ReadingQuestionTrial.QuestionName,
                    //    Answer = y.GlobalChangeAnswer
                    //}).ToList()
                }).ToListAsync();

            var oncologyReadingQuestions = await _readingOncologyTaskInfoRepository.Where(x => x.OncologyTaskId == inDto.VisitTaskId).ToListAsync();

            oncologyVisits.ForEach(x =>
            {
                var oncologyData = oncologyReadingQuestions.Where(y => y.VisitTaskId == x.VisitTaskId).FirstOrDefault();

                if (oncologyData != null)
                {
                    x.EvaluationResult = oncologyData.EvaluationResult;
                    x.EvaluationReason = oncologyData.EvaluationReason;
                }
                x.QuestionList = globalTaskReadingInfo.TaskList.Where(y => x.VisitTaskId == y.VisitTaskId).SelectMany(y => y.AfterQuestionList).Where(x => x.GlobalAnswerType == GlobalAnswerType.Question)
                .Select(y => new OncologyQuestion
                {
                    QuestionId = y.QuestionId ?? default(Guid),
                    QuestionName = y.QuestionName,
                    QuestionGenre=y.QuestionGenre,
                    DictionaryCode=y.DictionaryCode,
                    Answer = y.Answer
                }).ToList();
                x.IsHaveChange = globalTaskReadingInfo.TaskList.Where(y => x.VisitTaskId == y.VisitTaskId).SelectMany(y => y.AfterQuestionList).Any(y => y.IsHaveChange);
                x.VisitRemark = globalTaskReadingInfo.TaskList.Where(y => x.VisitTaskId == y.VisitTaskId).SelectMany(y => y.AfterQuestionList).Where(y => y.GlobalAnswerType == GlobalAnswerType.Reason).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;

            });

            result.OncologyVisits = oncologyVisits;

            List<CriterionDictionaryInfo> assessTypeList = await _readingTrialCriterionDictionaryRepository.Where(x => x.CriterionId == taskInfo.TrialReadingCriterionId
                  && x.ParentCode == ReadingCommon.CriterionDictionary.OncologyAssess
                  )
                  .Select(x => new CriterionDictionaryInfo()
                  {
                      Id = x.Id,
                      DictionaryId = x.DictionaryId,
                      ChildGroup = x.Dictionary.ChildGroup,
                      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;

        }

        /// <summary>
        /// 修改肿瘤学阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SetOncologyReadingInfo(SetOncologyReadingInfoInDto inDto)
        {
            await VerifyTaskIsSign(inDto.OncologyTaskId);
            await _readingOncologyTaskInfoRepository.BatchDeleteNoTrackingAsync(x => x.OncologyTaskId == inDto.OncologyTaskId);

            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.OncologyTaskId).FirstNotNullAsync();

            List<ReadingOncologyTaskInfo> readingOncologies = inDto.OncologyQuestionList.Select(x => new ReadingOncologyTaskInfo()
            {
                EvaluationReason = x.EvaluationReason,
                SubjectId = taskInfo.SubjectId,
                EvaluationResult = x.EvaluationResult,
                OncologyTaskId = inDto.OncologyTaskId,
                TrialId = taskInfo.TrialId,
                VisitTaskId = x.VisitTaskId
            }).ToList();

            await _readingOncologyTaskInfoRepository.AddRangeAsync(readingOncologies);

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

            var result = await _readingOncologyTaskInfoRepository.SaveChangesAsync();

            return ResponseOutput.Ok(result);


        }
        #endregion


        /// <summary>
        /// 添加肿瘤学阅片任务 其实这里无非是要判断临床数据是否签名 但是对于添加新的阅片期  其实没有临床数据 可以走之前的逻辑
        /// </summary>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task AddOncologyTask(Guid oncologModuleId)
        {

            // 判断是否读片完成
            var finishReading = false;


            var readModuleInfo = await _readModuleRepository.Where(x => x.Id == oncologModuleId && x.ModuleType == ModuleTypeEnum.Oncology).FirstOrDefaultAsync();



            // 如果当前是肿瘤学
            if (readModuleInfo != null)
            {
                // 先找到对应的全局阅片模块Id
                var globalreadModuleId = await _readModuleRepository.Where(x => x.SubjectVisitId == readModuleInfo.SubjectVisitId &&
                x.TrialReadingCriterionId== readModuleInfo.TrialReadingCriterionId&&
                x.ModuleType == ModuleTypeEnum.Global).Include(x=>x.SubjectVisit).Select(x => x.Id).FirstOrDefaultAsync();

                // 找到一个全局阅片任务是否有裁判任务

                var judgeVisitTaskId = await _visitTaskRepository.Where(x => x.SouceReadModuleId == globalreadModuleId && x.TaskState == TaskState.Effect
                && x.ReadingCategory == ReadingCategory.Global
                         && x.ReadingTaskState == ReadingTaskState.HaveSigned).Select(x => x.JudgeVisitTaskId).FirstOrDefaultAsync();

                // 获取系统配置
                var readingType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == readModuleInfo.TrialReadingCriterionId).Select(x => x.ReadingType).FirstOrDefaultAsync();

                // 判断阅片是否完成
                if (judgeVisitTaskId == null && (await _visitTaskRepository.Where(x => x.SouceReadModuleId == globalreadModuleId && x.TaskState == TaskState.Effect && x.ReadingCategory == ReadingCategory.Global
                         && x.ReadingTaskState == ReadingTaskState.HaveSigned && !x.IsAnalysisCreate && x.TrialReadingCriterionId == readModuleInfo.TrialReadingCriterionId
                       ).CountAsync() == (int)readingType))
                {

                    finishReading = true;
                }
                else if (judgeVisitTaskId != null && (await _visitTaskRepository.AnyAsync(x => x.Id == judgeVisitTaskId.Value && x.ReadingTaskState == ReadingTaskState.HaveSigned)))
                {
                    finishReading = true;
                }

                if (finishReading)
                {
                    // 获取临床数据
                    var clinicalData = await _readingClinicalDataService.GetReadingClinicalList(new GetReadingClinicalDataListIndto()
                    {
                        SubjectId = readModuleInfo.SubjectId,
                        ReadingId = readModuleInfo.Id,
                        TrialId = readModuleInfo.TrialId,
                        TrialReadingCriterionId= readModuleInfo.TrialReadingCriterionId,

                    });

                    // 判断是否临床数据都已经签名
                    if (!clinicalData.Any(x => !x.IsSign))
                    {

                        List<ReadingGenerataTaskDTO> needReadList = new List<ReadingGenerataTaskDTO>();

                        needReadList.Add(new ReadingGenerataTaskDTO()
                        {
                            IsUrgent = readModuleInfo.IsUrgent ?? false,
                            SubjectId = readModuleInfo.SubjectId,
                            ReadingName = readModuleInfo.ModuleName,
                            //VisitNum = readModuleInfo.SubjectVisit.VisitNum,
                            ReadModuleId = readModuleInfo.Id,
                            ReadingCategory = ReadingCategory.Oncology,
                        });

                        var originalVisitId = await _visitTaskRepository.Where(x => x.SouceReadModuleId == globalreadModuleId && x.TaskState == TaskState.Effect && x.ReadingCategory == ReadingCategory.Global
                           && x.ReadingTaskState == ReadingTaskState.HaveSigned && !x.IsAnalysisCreate && x.TrialReadingCriterionId == readModuleInfo.TrialReadingCriterionId
                           ).Select(x => x.Id).FirstOrDefaultAsync();
                        await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
                        {
                            OriginalVisitId= originalVisitId,
                            ReadingCategory = GenerateTaskCategory.Oncology,
                            TrialId = readModuleInfo.TrialId,
                            ReadingGenerataTaskList = needReadList
                        });
                    }
                }



            }
        }


        /// <summary>
        /// 提交肿瘤阅片结果
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task<IResponseOutput> SubmitOncologyReadingInfo(SubmitOncologyReadingInfoInDto inDto)
        {
            await VerifyTaskIsSign(inDto.OncologyTaskId);
            //var result = await this.SaveGlobalReadingInfo(inDto);

            //await FinishReadUpdateState(inDto.OncologyTaskId);
            await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.OncologyTaskId, x => new VisitTask()
            {
                ReadingTaskState = ReadingTaskState.HaveSigned,
                SignTime = DateTime.Now,
            });
            await _visitTaskRepository.SaveChangesAsync();

            // 创建任务关联关系
            await this.CreateTaskRelated(inDto.OncologyTaskId);
            return ResponseOutput.Ok(true);
        }
    }
}
