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 IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Application.Interfaces;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Caching.Memory;

namespace IRaCIS.Application.Services
{
    /// <summary>
    /// IR影像阅片
    /// </summary>
    [ApiExplorerSettings(GroupName = "Reading")]
    public partial class ReadingImageTaskService : BaseService, IReadingImageTaskService
    {

        private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
        private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository;
        private readonly IRepository<ReadingOncologyTaskInfo> _readingOncologyTaskInfoRepository;
        private readonly IVisitTaskHelpeService _visitTaskHelpeService;
        private readonly IVisitTaskService _visitTaskService;
        private readonly IReadingClinicalDataService _readingClinicalDataService;
        private readonly IReadingCalculateService _readingCalculateService;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<Subject> _subjectRepository;
        private readonly IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository;
        private readonly IRepository<ReadingCriterionPage> _readingCriterionPageRepository;
        private readonly IRepository<ReadingJudgeInfo> _readingJudgeInfoRepository;
        private readonly IRepository<ReadModule> _readModuleRepository;
        private readonly IRepository<ReadingCriterionDictionary> _readingCriterionDictionaryRepository;
        private readonly IRepository<TumorAssessment> _tumorAssessmentRepository;
        private readonly IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository;
        private readonly IRepository<ReadingTableQuestionSystem> _readingTableQuestionSystemRepository;
        private readonly IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository;
        private readonly IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository;
        private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
        private readonly IRepository<ReadingQuestionCriterionSystem> _readingQuestionCriterionSystemRepository;
        private readonly IRepository<ReadingQuestionSystem> _readingQuestionSystem;
        private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileSystem;
        private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository;

        private readonly IMemoryCache _cache;
        private readonly ITrialEmailNoticeConfigService _trialEmailNoticeConfigService;


        public ReadingImageTaskService(
                  IMapper mapper,
                  IRepository<NoneDicomStudy> noneDicomStudyRepository,
                  IRepository<VisitTask> visitTaskRepository,
                  IRepository<Trial> TrialRepository,
                  IRepository<ReadingTableQuestionAnswer> ReadingTableQuestionAnswerRepository,
                  IRepository<ReadingOncologyTaskInfo> ReadingOncologyTaskInfoRepository,
                  IVisitTaskHelpeService visitTaskHelpeService,
                  IVisitTaskService visitTaskService,
                  IReadingClinicalDataService readingClinicalDataService,
                  IReadingCalculateService readingCalculateService,
                  IRepository<SubjectVisit> subjectVisitRepository,
                  IRepository<Subject> subjectRepository,
                  IRepository<ReadingGlobalTaskInfo> readingGlobalTaskInfoRepository,
                  IRepository<ReadingCriterionPage> readingCriterionPageRepository,
                  IRepository<ReadingJudgeInfo> readingJudgeInfoRepository,
                  IRepository<ReadModule> readModuleRepository,
                  IMemoryCache cache,
                  IRepository<ReadingCriterionDictionary> readingCriterionDictionaryRepository,
                  IRepository<TumorAssessment> tumorAssessmentRepository,
                  IRepository<ReadingTableAnswerRowInfo> readingTableAnswerRowInfoRepository,
                  IRepository<ReadingTableQuestionSystem> readingTableQuestionSystemRepository,
                  IRepository<ReadingTableQuestionTrial> readingTableQuestionTrialRepository,
                  IRepository<ReadingTaskQuestionAnswer> readingTaskQuestionAnswerRepository,
                  IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository,
                  IRepository<ReadingQuestionCriterionSystem> readingQuestionCriterionSystemRepository,
                  IRepository<ReadingQuestionSystem> ReadingQuestionSystem,
                   ITrialEmailNoticeConfigService trialEmailNoticeConfigService,
                    IRepository<NoneDicomStudyFile> noneDicomStudyFileSystem,
                  IRepository<ReadingQuestionTrial> readingQuestionTrialRepository
          )
        {
            base._mapper = mapper;
            this._noneDicomStudyRepository = noneDicomStudyRepository;
            this._visitTaskRepository = visitTaskRepository;
            this._trialRepository = TrialRepository;
            this._readingTableQuestionAnswerRepository = ReadingTableQuestionAnswerRepository;
            this._readingOncologyTaskInfoRepository = ReadingOncologyTaskInfoRepository;
            this._visitTaskHelpeService = visitTaskHelpeService;
            this._visitTaskService = visitTaskService;
            this._readingClinicalDataService = readingClinicalDataService;
            this._readingCalculateService = readingCalculateService;
            this._subjectVisitRepository = subjectVisitRepository;
            this._subjectRepository = subjectRepository;
            this._readingGlobalTaskInfoRepository = readingGlobalTaskInfoRepository;
            this._readingCriterionPageRepository = readingCriterionPageRepository;
            this._readingJudgeInfoRepository = readingJudgeInfoRepository;
            this._readModuleRepository = readModuleRepository;
            this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository;
            this._tumorAssessmentRepository = tumorAssessmentRepository;
            this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository;
            this._readingTableQuestionSystemRepository = readingTableQuestionSystemRepository;
            this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository;
            this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository;
            this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
            this._readingQuestionCriterionSystemRepository = readingQuestionCriterionSystemRepository;
            this._readingQuestionSystem = ReadingQuestionSystem;
            this._noneDicomStudyFileSystem = noneDicomStudyFileSystem;
            this._readingQuestionTrialRepository = readingQuestionTrialRepository;
            this._cache = cache;
            this._trialEmailNoticeConfigService = trialEmailNoticeConfigService;
        }

        /// <summary>
        /// 阅读临床数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task ReadClinicalData(ReadClinicalDataInDto inDto)
        {
            await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask
            {
                IsReadClinicalData = true
            });
            await _visitTaskRepository.SaveChangesAsync();
        }

        /// <summary>
        /// 添加默认值到任务里面
        /// </summary>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task AddDefaultValueToTask(Guid visitTaskId)
        {
            var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();

            var questions = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == visitTaskInfo.TrialReadingCriterionId).ToListAsync();
            questions = questions.Where(x => !x.DefaultValue.IsNullOrEmpty()).ToList();

            var taskAnswerIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();
            questions = questions.Where(x => !taskAnswerIds.Contains(x.Id)).ToList();

            List<ReadingTaskQuestionAnswer> questionAnswers = questions.Select(x => new ReadingTaskQuestionAnswer()
            {

                Answer=x.DefaultValue,
                Id= NewId.NextGuid(),
                ReadingQuestionCriterionTrialId= visitTaskInfo.TrialReadingCriterionId,
                ReadingQuestionTrialId= x.Id,
                SubjectId= visitTaskInfo.SubjectId,
                TrialId= visitTaskInfo.TrialId,
                VisitTaskId=visitTaskId,
                
            }).ToList();

            await _readingTaskQuestionAnswerRepository.AddRangeAsync(questionAnswers);
            await _readingTaskQuestionAnswerRepository.SaveChangesAsync();

        }


        #region 阅片页面   关联信息查询 以及基本验证

        /// <summary>
        /// 根据任务ID获取ReadingTool
        /// </summary>
        /// <param name="indto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetReadingToolOutDto> GetReadingTool(GetReadingToolInDto indto)
        {
            var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).FirstNotNullAsync();

            var criterionTrialInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).FirstNotNullAsync();
            GetReadingToolOutDto result = new GetReadingToolOutDto()
            {
                TrialReadingCriterionId = visitTaskInfo.TrialReadingCriterionId,
                ReadingTool = criterionTrialInfo.ReadingTool,
                CriterionType = criterionTrialInfo.CriterionType,
            };

            return result;
        }

        /// <summary>
        /// 获取关联的阅片任务
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(List<GetRelatedVisitTaskOutDto>, object)> GetRelatedVisitTask(GetRelatedVisitTaskInDto inDto)
        {
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
            var baselineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.IsBaseLine && !x.IsLostVisit).Select(x => x.Id).FirstNotNullAsync();
            var result = await _visitTaskRepository
                .WhereIf(taskInfo.TaskState != TaskState.Effect, x => x.Id == inDto.VisitTaskId)
                .Where(x =>
            (x.TrialId == taskInfo.TrialId &&
            x.SubjectId == taskInfo.SubjectId &&
            x.ArmEnum == taskInfo.ArmEnum &&
            x.DoctorUserId == taskInfo.DoctorUserId &&
            x.ReadingTaskState == ReadingTaskState.HaveSigned &&
            x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
            x.TaskState == TaskState.Effect &&
            x.VisitTaskNum<= taskInfo.VisitTaskNum&&
            x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
            x.ReadingCategory == ReadingCategory.Visit) || x.Id == inDto.VisitTaskId)
                .Select(x => new GetRelatedVisitTaskOutDto()
                {
                    TaskBlindName = x.TaskBlindName,
                    TaskName = x.TaskName,
                    ReadingTaskState = x.ReadingTaskState,
                    VisitId = x.SourceSubjectVisitId,
                    VisitTaskId = x.Id,
                    VisitTaskNum = x.VisitTaskNum,
                    IsBaseLineTask = x.SourceSubjectVisitId == baselineVisitId,
                    IsCurrentTask = x.Id == inDto.VisitTaskId,

                }).OrderBy(x => x.VisitTaskNum).ToListAsync();

            if (!taskInfo.TrialReadingCriterion.IsReadingTaskViewInOrder)
            {
                result = result.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToList();
            }

            return (result, new
            {
                ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
            });
        }

        /// <summary>
        /// 获取既往任务名称和编号
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto)
        {
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
            var readingPastResultList = await _visitTaskRepository.Where(x =>
            x.TrialId == taskInfo.TrialId &&
            x.SubjectId == taskInfo.SubjectId &&
            x.VisitTaskNum<= taskInfo.VisitTaskNum&&
            x.ArmEnum == taskInfo.ArmEnum &&
            x.Id != inDto.VisitTaskId &&
            x.DoctorUserId == taskInfo.DoctorUserId &&
            x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
            x.ReadingTaskState == ReadingTaskState.HaveSigned &&
            x.TaskState == TaskState.Effect &&
            x.IsAnalysisCreate == taskInfo.IsAnalysisCreate)
            .WhereIf(taskInfo.ReadingCategory != ReadingCategory.Visit, x => x.ReadingCategory == taskInfo.ReadingCategory)

            .ProjectTo<GetReadingPastResultListOutDto>(_mapper.ConfigurationProvider).OrderBy(x => x.VisitTaskNum).ToListAsync();
            return readingPastResultList;
        }

        /// <summary>
        /// 获取阅片的受试者信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetReadingSubjectInfoOutDto> GetReadingSubjectInfo(GetReadingSubjectInfoInDto inDto)
        {
            var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstOrDefaultAsync();
            var subjectCode = await _subjectRepository.Where(x => x.Id == visitTask.SubjectId).Select(x => x.Code).FirstOrDefaultAsync();

            var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTask.TrialReadingCriterionId).Select(x => new
            {
                x.IsReadingShowPreviousResults,
                x.IsReadingShowSubjectInfo
            }).FirstOrDefaultAsync();
            var trialInfo = await _trialRepository.Where(x => x.Id == visitTask.TrialId).Select(x => new
            {
                x.ClinicalInformationTransmissionEnum,
            }).FirstOrDefaultAsync();

            return new GetReadingSubjectInfoOutDto()
            {
                VisitTaskId = visitTask.Id,
                SubjectId = visitTask.SubjectId,
                SubjectCode = visitTask.BlindSubjectCode.IsNullOrEmpty() ? subjectCode : visitTask.BlindSubjectCode,
                ReadingCategory = visitTask.ReadingCategory,
                TaskBlindName = visitTask.TaskBlindName,
                IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults,
                IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo,

            };
        }


        /// <summary>
        /// 验证是否为基线访视任务
        /// </summary>
        /// <param name="visitTaskId"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        private async Task VerifyIsBaseLineTask(Guid visitTaskId)
        {
            var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
            if (taskinfo.ReadingCategory != ReadingCategory.Visit)
            {
                throw new BusinessValidationFailedException("当前任务不是访视任务");
            }

            if (await _subjectVisitRepository.AnyAsync(x => x.Id == taskinfo.SourceSubjectVisitId && x.IsBaseLine))
            {
                throw new BusinessValidationFailedException("当前是基线任务,无法拆分和合并病灶");
            }
        }



        /// <summary>
        /// 验证任务是否签名
        /// </summary>
        /// <param name="visitTaskid"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        private async Task VerifyTaskIsSign(Guid visitTaskid)
        {
            if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.ReadingTaskState == ReadingTaskState.HaveSigned))
            {
                throw new BusinessValidationFailedException($"当前任务已经签名!");
            }


            if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect))
            {
                throw new BusinessValidationFailedException($"当前任务已失效!");
            }
        }



        #endregion


        #region 访视任务  - Dicom 阅片 表格问题相关查询


        /// <summary>
        /// 获取DIcom阅片问题答案
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(List<DicomReadingQuestionAnswer>, object)> GetDicomReadingQuestionAnswer(GetDicomReadingQuestionAnswerInDto inDto)
        {
            await AddDefaultValueToTask(inDto.VisitTaskId);
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
            var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id);

            return (result, new
            {

                ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
            });
        }

        /// <summary>
        /// 获取阅片外层问题
        /// </summary>
        /// <param name="trialReadingCriterionId"></param>
        /// <param name="visitTaskId"></param>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task<List<DicomReadingQuestionAnswer>> GetReadingQuestion(Guid trialReadingCriterionId,Guid? visitTaskId)
        {
           

            var criterionIdInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == trialReadingCriterionId).FirstNotNullAsync();
         

            //排除表格问题
            var questions = await _readingQuestionTrialRepository
                .WhereIf(criterionIdInfo.IseCRFShowInDicomReading, x=>x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.Type != ReadingQestionType.Table)
                .WhereIf(!criterionIdInfo.IseCRFShowInDicomReading, x=>x.IsShowInDicom && x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.Type != ReadingQestionType.Table)
               
                .ProjectTo<DicomReadingQuestionAnswer>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();


            var answers = new List<ReadingTaskQuestionAnswer>();

            if (visitTaskId != null)
            {
                answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).ToListAsync(); ;
            }
        

            //排除表格问题 同时排除组问题
            var groups = questions.Where(x => x.Type != ReadingQestionType.Group).Select(x => x.GroupName).ToList();

            var result = questions.Where(x => x.Type == ReadingQestionType.Group && groups.Contains(x.GroupName)).ToList();

            foreach (var item in result)
            {
                GetDicomReadingAnswer(item, questions, answers);
            }

            return result;
        }

        private void GetDicomReadingAnswer(DicomReadingQuestionAnswer item, List<DicomReadingQuestionAnswer> questions, List<ReadingTaskQuestionAnswer> answers)
        {
            item.Answer = answers.Where(x => x.ReadingQuestionTrialId == item.Id).Select(x => x.Answer).FirstIsNullReturnEmpty();
            
            item.Childrens = questions.Where(x => x.ParentId == item.Id || ((item.Type == ReadingQestionType.Group && x.Type != ReadingQestionType.Group && x.ParentId == null && x.GroupName == item.GroupName))).ToList();
            if (item.Childrens != null && item.Childrens.Count > 0)
            {
                foreach (var question in item.Childrens)
                {
                    GetDicomReadingAnswer(question, questions, answers);
                }
            }

        }

        /// <summary>
        /// 获取阅片报告
        /// </summary>
        /// <param name="indto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetReadingReportEvaluationOutDto> GetReadingReportEvaluation(GetReadingReportEvaluationInDto indto)
        {
            return await _readingCalculateService.GetReadingReportEvaluation(indto);
        }

        /// <summary>
        /// 获取表格答案行信息 
        /// </summary>
        /// <param name="inDto"></param>
        /// <remarks>
        /// (QuestionId) 可为空
        /// </remarks>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<GetTableAnswerRowInfoOutDto>> GetTableAnswerRowInfoList(GetTableAnswerRowInfoInDto inDto)
        {
            await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto()
            {
                VisitTaskId = inDto.VisitTaskId
            });
            var result = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId)
                .WhereIf(inDto.QuestionId != null, x => x.QuestionId == inDto.QuestionId)
                .ProjectTo<GetTableAnswerRowInfoOutDto>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex)
                .ToListAsync();
            result.ForEach(x =>
            {

                x.OrderMarkName = x.OrderMark + x.RowIndexNum.GetLesionMark();
            });
            return result;
        }

        /// <summary>
        /// 获取表格问题及答案(2022-08-26)
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(GetReadingQuestionAndAnswerOutDto, object)> GetReadingQuestionAndAnswer(GetReadingQuestionAndAnswerInDto inDto)
        {

            await AddDefaultValueToTask(inDto.VisitTaskId);
            var result = new GetReadingQuestionAndAnswerOutDto();

            var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();

            var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).FirstNotNullAsync();

            result.ReadingTaskState = taskinfo.ReadingTaskState;
            var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskinfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync();

            result.IsBaseLineTask = taskinfo.SourceSubjectVisitId == baseLineVisitId;

            var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
          

            var tableAnswers = await _readingTableQuestionAnswerRepository
                  .ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
                .Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();

            var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();

            var questionPage = await GetReadingTableQuestion(taskinfo.TrialReadingCriterionId, inDto.VisitTaskId, tableAnswers, tableAnsweRowInfos);

            result.SinglePage = questionPage.SinglePage;
            result.MultiPage = questionPage.MultiPage;
            result.PublicPage = questionPage.PublicPage;
            result.BlindName = visitTaskInfo.TaskBlindName;
            result.TaskNum = visitTaskInfo.VisitTaskNum;

            return (result, new
            {
                readingTaskState = visitTaskInfo.ReadingTaskState,
                FormType = criterionInfo.FormType,
                TaskNum = visitTaskInfo.VisitTaskNum,

            }); ;
        }

        /// <summary>
        /// 获取表格问题及答案  只返回表格问题(任务和标准)
        /// </summary>
        /// <param name="trialReadingCriterionId"></param>
        /// <param name="taskId"></param>
        /// <param name="tableAnswers"></param>
        /// <param name="tableAnsweRowInfos"></param>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task<GetReadingTableQuestionOutDto> GetReadingTableQuestion(Guid trialReadingCriterionId, Guid? taskId, List<ReadingTableQuestionAnswerInfo> tableAnswers, List<TableAnsweRowInfo> tableAnsweRowInfos,bool isGetallQuestion=false) 
        {
            var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == trialReadingCriterionId).FirstNotNullAsync();

            var qusetionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId).ProjectTo<TrialReadQuestionData>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();

            // 是否获取所有问题
            if (isGetallQuestion)
            {
                if (!criterionInfo.IseCRFShowInDicomReading)
                {
                    qusetionList = qusetionList.Where(x => x.IsShowInDicom).OrderBy(x => x.ShowOrder).ToList();
                }
            }
            else
            {
                if (!criterionInfo.IseCRFShowInDicomReading)
                {
                    qusetionList = qusetionList.Where(x => x.IsShowInDicom && (x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.Group)).OrderBy(x => x.ShowOrder).ToList();
                }
                var usedGurops = qusetionList.Where(x => x.Type == ReadingQestionType.Table).Select(x => x.GroupName).ToList();
                qusetionList = qusetionList.Where(x => usedGurops.Contains(x.GroupName)).ToList();
            }
          

            if (taskId != null)
            {
                var answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == taskId).ToListAsync();
                qusetionList.ForEach(x =>
                {
                    x.Answer = answers.Where(y => y.ReadingQuestionTrialId == x.Id).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
                });

            }

            #endregion

            var groupList = new List<TrialReadQuestionData>();
            var qusetionIds = qusetionList.Select(x => x.Id).ToList();

            var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => qusetionIds.Contains(x.ReadingQuestionId))
                .ProjectTo<TableQuestionTrial>(_mapper.ConfigurationProvider)
               .OrderBy(x => x.ShowOrder).ToListAsync();

            var result = new GetReadingTableQuestionOutDto();
            if (criterionInfo.FormType == FormType.MultiplePage)
            {
                qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId != null).ToList();
                var readingCriterionPageIds = qusetionList.OrderBy(x => x.PageShowOrder).Select(x => x.ReadingCriterionPageId).Distinct().ToList();
                foreach (var item in readingCriterionPageIds)
                {
                    var newPageQusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == item).ToList();
                    var firstData = newPageQusetionList.FirstOrDefault();
                    var page = new TrialReadQuestionData()
                    {
                        PageName = firstData.PageName,
                        IsPage = true,
                        IsPublicPage = firstData.IsPublicPage,
                    };

                    var pageGroupList = newPageQusetionList.Where(x => x.Type == ReadingQestionType.Group || (x.ParentId == null && x.GroupName.IsNullOrEmpty())).ToList();
                    pageGroupList.ForEach(x =>
                    {
                        this.FindChildQuestion(x, newPageQusetionList, tableQuestionList, tableAnswers, tableAnsweRowInfos);
                    });

                    page.Childrens = pageGroupList.Where(x => !(x.Type == ReadingQestionType.Group && x.Childrens.Count() == 0)).ToList();
                    groupList.Add(page);
                }

                result.PublicPage = groupList.Where(x => x.IsPublicPage.Value).ToList();
                result.MultiPage = groupList.Where(x => !x.IsPublicPage.Value).ToList();
            }
            else
            {
                qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == null).ToList();

                groupList = qusetionList.Where(x => x.Type == ReadingQestionType.Group || (x.ParentId == null && x.GroupName.IsNullOrEmpty())).ToList();
                groupList.ForEach(x =>
                {
                    this.FindChildQuestion(x, qusetionList, tableQuestionList, tableAnswers, tableAnsweRowInfos);
                });

                groupList = groupList.Where(x => !(x.Type == ReadingQestionType.Group && x.Childrens.Count() == 0)).ToList();

                result.SinglePage = groupList;


            }


            return result;
        }

        /// <summary>
        /// 获取子元素
        /// </summary>
        /// <param name="item"></param>
        /// <param name="questionlists"></param>
        /// <param name="tableQuestionLists"></param>
        private void FindChildQuestion(TrialReadQuestionData item, List<TrialReadQuestionData> questionlists, List<TableQuestionTrial> tableQuestionLists, List<ReadingTableQuestionAnswerInfo> tableAnswers, List<TableAnsweRowInfo> tableAnsweRowInfos)
        {
            item.Childrens = questionlists.Where(x => x.ParentId == item.Id || (item.Type == ReadingQestionType.Group && x.Type != ReadingQestionType.Group && x.ParentId == null && x.GroupName == item.GroupName)).ToList();
            item.TableQuestions = new TrialReadTableQuestion();

            item.TableQuestions.Questions = tableQuestionLists.Where(x => x.ReadingQuestionId == item.Id).OrderBy(x => x.ShowOrder).ToList();

            item.TableQuestions.Questions.ForEach(x =>
            {

                x.RelationQuestions = tableQuestionLists.Where(z => (z.DependParentId ?? default(Guid)) == x.Id).Select(x => new GetTrialReadingQuestionOutDto
                {
                    Childrens = new List<GetTrialReadingQuestionOutDto>(),
                    ShowOrder = x.ShowOrder,
                    GroupName = string.Empty,
                    Id = x.Id,
                    DictionaryCode = x.DictionaryCode,
                    Type = x.Type,
                    TableQuestionType = x.TableQuestionType,
                    DependParentId = x.DependParentId,
                    IsDepend = x.IsDepend,
                    QuestionMark = x.QuestionMark,
                    TypeValue = x.TypeValue,
                    RelevanceId = x.RelevanceId,
                    RelevanceValue = x.RelevanceValue,
                    ImageCount = 0,
                    ParentId = item.Id,
                    DataTableColumn = x.DataTableColumn,
                    LesionType = item.LesionType,
                    QuestionName = x.QuestionName,
                    RelationQuestions = new List<GetTrialReadingQuestionOutDto>(),
                    Remark = x.Remark,
                    ValueType = x.ValueType,
                    Unit = x.Unit,
                }).ToList();
            });
            var thisAnswer = tableAnswers.Where(x => x.QuestionId == item.Id).ToList();
            var orders = thisAnswer.Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList();
            item.TableQuestions.Answers = new List<Dictionary<string, string>>();
            orders.ForEach(x =>
            {
                Dictionary<string, string> answers = new Dictionary<string, string>();
                var rowInfo = tableAnsweRowInfos.Where(y => y.RowIndex == x && y.QuestionId == item.Id).FirstOrDefault();
                var rowAnswer = thisAnswer.Where(y => y.RowId == rowInfo.Id).OrderBy(y => y.ShowOrder).ToList();
                rowAnswer.ForEach(z =>
                {
                    answers.Add(z.TableQuestionId.ToString(), z.Answer);
                });

              

                answers.Add("BlindName", rowInfo.BlindName);
                answers.Add("IsDicomReading", rowInfo.IsDicomReading.ToString());
                answers.Add("MeasureData", rowInfo == null ? string.Empty : rowInfo.MeasureData);
                answers.Add("RowIndex", x.ToString());
                answers.Add("RowId", rowInfo.Id.ToString());
                answers.Add("StudyId", rowInfo.StudyId.ToString());
                answers.Add("IsCanEditPosition", rowInfo.IsCanEditPosition.ToString());
                answers.Add("InstanceId", rowInfo == null ? string.Empty : rowInfo.InstanceId.ToString());
                answers.Add("SeriesId", rowInfo == null ? string.Empty : rowInfo.SeriesId.ToString());
                answers.Add("IsCurrentTaskAdd", rowInfo == null ? false.ToString() : rowInfo.IsCurrentTaskAdd.ToString());
                answers.Add("SplitOrMergeLesionName", rowInfo.SplitName.IsNullOrEmpty() ? rowInfo.MergeName : rowInfo.SplitName);
                answers.Add("SplitOrMergeType", rowInfo.SplitOrMergeType == null ? string.Empty : ((int)rowInfo.SplitOrMergeType).ToString());


                item.TableQuestions.Answers.Add(answers);
            });

            if (item.Childrens != null && item.Childrens.Count != 0)
            {
                item.Childrens.ForEach(x =>
                {
                    this.FindChildQuestion(x, questionlists, tableQuestionLists, tableAnswers, tableAnsweRowInfos);
                });
            }
        }



      

        #region 访视任务  - Dicom 阅片 表格问题 病灶的拆分与合并


        /// <summary>
        /// 拆分病灶
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task SplitLesion(SplitLesionInDto inDto)
        {
            await VerifyTaskIsSign(inDto.VisitTaskId);
            await this.VerifyIsBaseLineTask(inDto.VisitTaskId);
            var rowAnswer = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).AsNoTracking().FirstNotNullAsync();
            var tableAnswers = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == rowAnswer.RowIndex && x.QuestionId == inDto.QuestionId).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
            var maxRowIndex = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.RowIndex < Math.Floor(rowAnswer.RowIndex + 1)).OrderByDescending(x => x.RowIndex).Select(x => x.RowIndex).FirstOrDefaultAsync();
            var newRowIndex = maxRowIndex + (decimal)0.01;

            rowAnswer.RowIndex = newRowIndex;
            rowAnswer.MergeRowId = null;
            rowAnswer.SplitOrMergeType = SplitOrMergeType.Split;
            rowAnswer.SplitRowId = rowAnswer.Id;
            rowAnswer.Id = NewId.NextGuid();
            rowAnswer.InstanceId = null;
            rowAnswer.SeriesId = null;
            rowAnswer.IsCurrentTaskAdd = true;
            rowAnswer.MeasureData = string.Empty;

            List<QuestionMark?> needRemoveMark = new List<QuestionMark?>()
            {
                QuestionMark.MajorAxis,
                QuestionMark.ShortAxis,
            };

            tableAnswers.ForEach(x =>
            {
                x.Id = NewId.NextGuid();
                x.RowIndex = newRowIndex;
                x.VisitTaskId = inDto.VisitTaskId;
                x.RowId = rowAnswer.Id;
                x.Answer = needRemoveMark.Contains(x.ReadingTableQuestionTrial.QuestionMark) ? string.Empty : x.Answer;
                x.ReadingTableQuestionTrial = null;
            });
            await _readingTableAnswerRowInfoRepository.AddAsync(rowAnswer);
            await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers);
            await _readingTableAnswerRowInfoRepository.SaveChangesAsync();

        }

        /// <summary>
        /// 合并病灶
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task MergeLesion(MergeLesionInDto inDto)
        {
            await VerifyTaskIsSign(inDto.VisitTaskId);
            await this.VerifyIsBaseLineTask(inDto.VisitTaskId);

            var rowsInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && (x.Id == inDto.MainRowId || x.Id == inDto.MergeRowId)).ToListAsync();

            if (rowsInfo.Count() != 2)
            {
                throw new BusinessValidationFailedException("合并的病灶并非同一个访视任务");
            }


            var minaid = rowsInfo.Where(x => x.Id == inDto.MainRowId).Select(x => x.Id).FirstOrDefault();
            var mergeid = rowsInfo.Where(x => x.Id == inDto.MergeRowId).Select(x => x.Id).FirstOrDefault();

            List<QuestionMark?> needRemoveMark = new List<QuestionMark?>()
            {
                QuestionMark.MajorAxis,
                QuestionMark.ShortAxis,
            };

            var mainAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.RowId == minaid).Include(x => x.ReadingTableQuestionTrial).ToListAsync();

            foreach (var item in mainAnswer)
            {
                await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == mergeid && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
                {
                    Answer = needRemoveMark.Contains(item.ReadingTableQuestionTrial.QuestionMark) ? string.Empty : item.Answer,
                });
            }



            await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(mergeid, x => new ReadingTableAnswerRowInfo()
            {
                MergeRowId = minaid,
                SplitOrMergeType = SplitOrMergeType.Merge,
            });


            await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(mergeid, x => new ReadingTableAnswerRowInfo()
            {
                MergeRowId = minaid,
                SplitOrMergeType = SplitOrMergeType.Merge,
            });

            await _readingTableAnswerRowInfoRepository.SaveChangesAsync();


        }


        #endregion



        #region 访视任务  - Dicom 阅片 提交、修改

        /// <summary>
        /// 修改Dicom阅片问题
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> ChangeDicomReadingQuestionAnswer(ChangeDicomReadingQuestionAnswerInDto inDto)
        {
            await VerifyTaskIsSign(inDto.VisitTaskId);
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
            var criterionId = taskInfo.TrialReadingCriterionId;
            var questionIds = inDto.Answers.Select(x => x.Id).ToList();
            await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.ReadingQuestionTrialId));
            var needAddAnswer = inDto.Answers.Select(x => new ReadingTaskQuestionAnswer()
            {

                Answer = x.Answer,
                SubjectId = taskInfo.SubjectId,
                ReadingQuestionCriterionTrialId = criterionId,
                ReadingQuestionTrialId = x.Id,
                TrialId = taskInfo.TrialId,
                VisitTaskId = inDto.VisitTaskId,

            }).ToList();
            await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddAnswer);
            await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
            return ResponseOutput.Ok(true);
        }


        /// <summary>
        /// 删除表格行数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> DeleteReadingRowAnswer(DeleteReadingRowAnswerInDto inDto)
        {
            await VerifyTaskIsSign(inDto.VisitTaskId);

            var deleteRowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).FirstNotNullAsync();
            if (deleteRowInfo == null)
            {
                return ResponseOutput.Ok(true);
            }


            if (await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.SplitRowId == deleteRowInfo.Id && x.MergeRowId == deleteRowInfo.Id))
            {
                throw new BusinessValidationFailedException($"当前病灶分裂出其他病灶或者其他病灶合并到了当前病灶,删除失败");
            }

            var index = await _readingCalculateService.GetDeleteLesionStatrIndex(inDto);
            await _readingTableQuestionAnswerRepository.DeleteFromQueryAsync(x => x.RowId == inDto.RowId);
            await _readingTableAnswerRowInfoRepository.DeleteFromQueryAsync(x => x.Id == inDto.RowId);
            await _readingTableAnswerRowInfoRepository.SaveChangesAsync();


            var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId).Include(x=>x.ReadingQuestionTrial).OrderBy(x => x.RowIndex).ToListAsync();

           
            foreach (var item in rowInfoList.Where(x => x.RowIndex % 1 == 0))
            {
                string measureDataStr = string.Empty;
                if (item.MeasureData != null && item.MeasureData != string.Empty)
                {
                    dynamic measureData = JObject.Parse(item.MeasureData);
                    measureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index).GetLesionMark();
                    measureDataStr = JsonConvert.SerializeObject(measureData);
                }
               

                await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
                {
                    RowIndex = index
                });
                await _readingTableAnswerRowInfoRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
                {
                    RowIndex = index,
                    MeasureData = measureDataStr,
            });
                var spiltList = rowInfoList.Where(x => x.RowIndex % 1 != 0 && x.RowIndex > item.RowIndex && x.RowIndex < Math.Floor(item.RowIndex + 1)).OrderBy(x => x.RowIndex).ToList();
                decimal spiltindex = 0.01M;
                foreach (var spiltitem in spiltList)
                {
                    string spiltmeasureDataStr = string.Empty;
                    if (spiltitem.MeasureData != null && spiltitem.MeasureData != string.Empty)
                    {
                        dynamic spiltmeasureData = JObject.Parse(spiltitem.MeasureData);
                        spiltmeasureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index + spiltindex).GetLesionMark();
                         spiltmeasureDataStr = JsonConvert.SerializeObject(spiltmeasureData);
                    }
                    await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
                    {
                        RowIndex = index + spiltindex
                    });
                    await _readingTableAnswerRowInfoRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
                    {
                        RowIndex = index + spiltindex,
                        MeasureData= spiltmeasureDataStr,
                    });

                    spiltindex += 0.01M;
                }
                index++;
            }

            return ResponseOutput.Ok(true);
        }


        /// <summary>
        /// 提交表格问题答案  病灶
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<SubmitTableQuestionOutDto> SubmitTableQuestion(SubmitTableQuestionInDto inDto)
        {
            SubmitTableQuestionOutDto result = new SubmitTableQuestionOutDto();
            await VerifyTaskIsSign(inDto.VisitTaskId);
            var criterionId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.TrialReadingCriterionId).FirstOrDefaultAsync();
            var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == criterionId).FirstNotNullAsync();
            var tableQuestionIds = inDto.AnswerList.Select(x => x.TableQuestionId).ToList();

            var tableQuestionIdGroup = tableQuestionIds.GroupBy(x => new { TableQuestionId = x }).Select(x => new TableQuestionData
            {
                TableQuestionId = x.Key.TableQuestionId,
                Count = x.Count()
            }).ToList();

            if (tableQuestionIdGroup.Any(x => x.Count > 1))
            {
                throw new BusinessValidationFailedException($"相同问题传入两次!");
            }

            if (inDto.RowIndex % 1 == 0)
            {
                var questionInfo = await _readingQuestionTrialRepository.Where(x => x.Id == inDto.QuestionId).FirstNotNullAsync();
                if (questionInfo.MaxQuestionCount != null&& questionInfo.MaxQuestionCount!=0)
                {
                    if (questionInfo.MaxQuestionCount <
                        (
                        (await _readingTableAnswerRowInfoRepository.Where(x => x.RowIndex != inDto.RowIndex && ((x.RowIndex % 1) == 0) && x.VisitTaskId == inDto.VisitTaskId
                       && x.QuestionId == inDto.QuestionId
                    ).CountAsync()) + 1))
                    {
                        throw new BusinessValidationFailedException($"当前提交问题最大问题数为{questionInfo.MaxQuestionCount}!");
                    }
                }


                var tableQuestions = await _readingTableQuestionTrialRepository.Where(x => tableQuestionIds.Contains(x.Id) && x.MaxRowCount != null && x.MaxRowCount != 0).ToListAsync();

                foreach (var item in tableQuestions)
                {
                    var answer = inDto.AnswerList.Where(x => x.TableQuestionId == item.Id).Select(x => x.Answer).FirstOrDefault();
                    if (!answer.IsNullOrEmpty())
                    {
                        var rowCount = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.TableQuestionId == item.Id && ((x.RowIndex % 1) == 0) && x.Answer == answer && x.RowIndex != inDto.RowIndex).CountAsync();

                        if (rowCount > item.MaxRowCount.Value - 1)
                        {
                           
                            Dictionary<CriterionType, string> errorMsgDic = new Dictionary<CriterionType, string>()
                            {
                               {CriterionType.RECIST1Pointt1, $"按照RECIST1.1的相关规则,同一器官的靶病灶数量不超过{item.MaxRowCount.Value}个,请确认!"},
                            };
                            string msg = string.Empty;
                            try
                            {
                                msg = errorMsgDic[criterionInfo.CriterionType];
                            }
                            catch (Exception)
                            {

                                msg=$"问题{item.QuestionName}最大相同问题数为{item.MaxRowCount.Value},当前已存在{rowCount}条!";
                            }

                            throw new BusinessValidationFailedException(msg);
                        }
                    }
                }
            }
            var isCurrentTaskAddList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.TrialId == inDto.TrialId && x.RowIndex == inDto.RowIndex).Select(x => x.IsCurrentTaskAdd).ToListAsync();
            bool isCurrentTaskAdd = true;
            if (isCurrentTaskAddList.Count() > 0)
            {
                isCurrentTaskAdd = isCurrentTaskAddList[0];
            }


            ReadingTableAnswerRowInfo rowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.TrialId == inDto.TrialId && x.RowIndex == inDto.RowIndex).AsNoTracking().FirstOrDefaultAsync();

            rowInfo = rowInfo == null ? new ReadingTableAnswerRowInfo() : rowInfo;

            await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.TrialId == inDto.TrialId && x.RowIndex == inDto.RowIndex);
            await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.TrialId == inDto.TrialId && x.RowIndex == inDto.RowIndex);

            rowInfo.Id =inDto.RowId==null?  NewId.NextGuid(): inDto.RowId.Value;
            rowInfo.TrialId = inDto.TrialId;
            rowInfo.QuestionId = inDto.QuestionId;
            rowInfo.MeasureData = inDto.MeasureData;
            rowInfo.BlindName = inDto.BlindName;
            rowInfo.IsDicomReading = inDto.IsDicomReading;
            rowInfo.IsCurrentTaskAdd = isCurrentTaskAdd;
            rowInfo.FristAddTaskNum = inDto.FristAddTaskNum;
            rowInfo.RowIndex = inDto.RowIndex;
            rowInfo.InstanceId = inDto.InstanceId;
            rowInfo.SeriesId = inDto.SeriesId;
            rowInfo.VisitTaskId = inDto.VisitTaskId;
            rowInfo.StudyId = inDto.StudyId;
            rowInfo.IsCanEditPosition = inDto.IsCanEditPosition;
            result.RowId = rowInfo.Id;

            List<ReadingTableQuestionAnswer> answerList = inDto.AnswerList.Select(x => new ReadingTableQuestionAnswer()
            {
                Answer = x.Answer,
                Id = NewId.NextGuid(),
                TrialId = inDto.TrialId,
                QuestionId = inDto.QuestionId,
                TableQuestionId = x.TableQuestionId,
                RowIndex = inDto.RowIndex,
                RowId = rowInfo.Id,
                VisitTaskId = inDto.VisitTaskId
            }).ToList();


            await _readingTableAnswerRowInfoRepository.AddAsync(rowInfo);
            await _readingTableQuestionAnswerRepository.AddRangeAsync(answerList);

            await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask()
            {
                ReadingTaskState = ReadingTaskState.Reading,

            });
            await _readingTableQuestionAnswerRepository.SaveChangesAsync();
            await this._readingCalculateService.CalculateTask(new CalculateTaskInDto()
            {
                IsChangeOtherTask = false,
                VisitTaskId = inDto.VisitTaskId,
            });




            return result;
        }



        /// <summary>
        /// 提交Dicom阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task<IResponseOutput> SubmitDicomVisitTask(SubmitDicomVisitTaskInDto inDto)
        {


            await VerifyTaskIsSign(inDto.VisitTaskId);

            // 修改编号

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

            // 获取标准表格外层问题
            var questionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.LesionType != null && x.ReadingTableQuestionTrialList.Any(x => x.QuestionMark == QuestionMark.AutoId))
                .SelectMany(x => x.ReadingTableQuestionTrialList).Where(x => x.QuestionMark == QuestionMark.AutoId).Select(x => new
                {
                    x.ReadingQuestionId,
                    TableQuestionId = x.Id,

                }).ToListAsync();

            var questionIds = questionList.Select(x => x.ReadingQuestionId).ToList();

            var questionMarkList = await _readingQuestionTrialRepository.Where(x => questionIds.Contains(x.Id)).Select(x => new
            {
                QuestionId = x.Id,
                x.OrderMark,

            }).ToListAsync();

            var rowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.QuestionId)).ToListAsync();
            List<ReadingTableQuestionAnswer> questionAnswerList = new List<ReadingTableQuestionAnswer>();
            foreach (var item in questionList)
            {
                await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == item.ReadingQuestionId
                && x.TableQuestionId == item.TableQuestionId && x.VisitTaskId == inDto.VisitTaskId);

                var orderMark = questionMarkList.Where(x => x.QuestionId == item.ReadingQuestionId).Select(x => x.OrderMark).FirstOrDefault();

                foreach (var row in rowInfo.Where(x => x.QuestionId == item.ReadingQuestionId))
                {
                    questionAnswerList.Add(new ReadingTableQuestionAnswer()
                    {
                        Answer = orderMark + row.RowIndex.GetLesionMark(),
                        Id = NewId.NextGuid(),
                        QuestionId = item.ReadingQuestionId,
                        RowId = row.Id,
                        RowIndex = row.RowIndex,
                        TableQuestionId = item.TableQuestionId,
                        TrialId = taskInfo.TrialId,
                        VisitTaskId = taskInfo.Id,

                    });
                }
            }
            await _readingTableQuestionAnswerRepository.AddRangeAsync(questionAnswerList);
            await _readingTableQuestionAnswerRepository.SaveChangesAsync();




            await this.SubmitTaskChangeState(inDto.VisitTaskId);
            return ResponseOutput.Ok(true);
        }




        #endregion


        #region Dicom  非dicom   公用


        /// <summary>
		/// 验证访视提交
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
        {
            await VerifyTaskIsSign(inDto.VisitTaskId);
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();

            var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId
            && (x.IsJudgeQuestion || (x.IsRequired == IsRequired.Required&&x.ShowQuestion==ShowQuestion.Show))
            ).ToListAsync();

            var answerQuestionIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();

            readingQuestionList = readingQuestionList.Where(x => !answerQuestionIds.Contains(x.Id)).ToList();

            if (readingQuestionList.Count() > 0)
            {
                throw new BusinessValidationFailedException($" 必填问题{ string.Join(',', readingQuestionList.Select(x => x.QuestionName))}的答案为空或未保存");
            }

            await _readingCalculateService.VerifyVisitTaskQuestions(inDto);

            if ((await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
            {

                SubjectId = taskInfo.SubjectId,
                TrialId = taskInfo.TrialId,
                VisitTaskId = taskInfo.Id,
            })).Count() > 0 && !taskInfo.IsReadClinicalData)
            {
                throw new BusinessValidationFailedException($"临床数据未阅读!");
            }
          

           
            return ResponseOutput.Ok(true);
        }




        /// <summary>
        /// 获取下一个阅片任务
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetReadingTaskDto> GetNextTask(GetNextTaskInDto inDto)
        {
            if (inDto.VisitTaskId == null)
            {
                await VerifyReadingRestTime();
            }

            GetReadingTaskDto? task = new GetReadingTaskDto();

            var trialReadingCriterionId = inDto.TrialReadingCriterionId;


            if (trialReadingCriterionId == null && inDto.VisitTaskId == null)
            {
                throw new BusinessValidationFailedException("当没有任务Id的时候,标准Id必传");
            }

            if (inDto.VisitTaskId != null)
            {
                task = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new GetReadingTaskDto()
                {
                    VisitTaskId = x.Id,
                    TaskBlindName = x.TaskBlindName,
                    SubjectId = x.SubjectId,
                    ReadingCategory = x.ReadingCategory,
                    VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : default(Guid),
                    VisitNum = x.VisitTaskNum,
                    TrialReadingCriterionId = x.TrialReadingCriterionId,

                }).FirstOrDefaultAsync();

                trialReadingCriterionId = task.TrialReadingCriterionId;

            }
            else if (inDto.SubjectId != null)
            {
                var subjectTaskList = await _visitTaskService.GetOrderReadingIQueryable(inDto.TrialId, trialReadingCriterionId).Item2.ToListAsync();

                var index = 0;
                subjectTaskList.ForEach(x =>
                {
                    x.Index = index;
                    index++;
                });

                var subjectIndex = subjectTaskList.Where(x => x.SubjectId == inDto.SubjectId && x.SubjectCode == inDto.SubjectCode).Select(x => x.Index).FirstOrDefault();

                var currentSubject = subjectTaskList.Where(x => x.SubjectId == inDto.SubjectId && x.SubjectCode == inDto.SubjectCode&& x.Index >= subjectIndex && !x.ExistReadingApply).OrderBy(x => x.Index).FirstOrDefault();

                if (currentSubject == null)
                {
                    throw new BusinessValidationFailedException("当前受试者此次阅片任务已全部完成!");
                }

                task = currentSubject.UnReadTaskList.Select(x => new GetReadingTaskDto()
                {
                    ReadingCategory = x.ReadingCategory,
                    SubjectCode = currentSubject.SubjectCode,
                    SubjectId = currentSubject.SubjectId,
                    TaskBlindName = x.TaskBlindName,
                    VisitNum = x.VisitNum,
                    VisistId = x.VisistId ?? default(Guid),
                    VisitTaskId = x.Id,
                    TrialReadingCriterionId = x.TrialReadingCriterionId,
                }).FirstOrDefault();



            }
            else
            {
                task = await _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.TrialReadingCriterionId == trialReadingCriterionId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.DoctorUserId == _userInfo.Id
                && x.TrialReadingCriterionId == trialReadingCriterionId
                && x.TaskState == TaskState.Effect).Select(x => new GetReadingTaskDto()
                {
                    VisitTaskId = x.Id,
                    TaskBlindName = x.TaskBlindName,
                    ReadingCategory = x.ReadingCategory,
                    VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : x.ReadModule == null ? default(Guid) : x.ReadModule.SubjectVisitId,
                    VisitNum = x.VisitTaskNum,
                    SubjectId = x.SubjectId,
                    SubjectCode = x.Subject.Code,
                    TrialReadingCriterionId = x.TrialReadingCriterionId,
                }).FirstOrDefaultAsync();
                if (task == null)
                {
                    throw new BusinessValidationFailedException("当前受试者此次阅片任务已全部完成!");
                }
            }

            if (task.SubjectCode.IsNullOrEmpty())
            {
                task.SubjectCode = await _subjectRepository.Where(x => x.Id == task.SubjectId).Select(x => x.Code).FirstOrDefaultAsync();
            }

            await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId && x.FirstReadingTime == null, x => new VisitTask()
            {
                FirstReadingTime = DateTime.Now,
            });
            await _visitTaskRepository.SaveChangesAsync();

            var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).FirstNotNullAsync();

            task.SubjectCode = visitTaskInfo.BlindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : visitTaskInfo.BlindSubjectCode;


            var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).Select(x => new
            {
                x.IsReadingShowPreviousResults,
                x.IsReadingShowSubjectInfo,
                x.DigitPlaces,
                x.CriterionType,
            }).FirstOrDefaultAsync();

            task.IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults;
            task.IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo;
            if (visitTaskInfo.SourceSubjectVisitId != null)
            {
                task.IsExistsNoDicomFile = await _noneDicomStudyRepository.AnyAsync(x => x.SubjectVisitId == visitTaskInfo.SourceSubjectVisitId && x.FileCount > 0);
            }
            task.IsExistsClinicalData = (await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
            {

                SubjectId = task.SubjectId,
                TrialId = inDto.TrialId,
                VisitTaskId = task.VisitTaskId,
            })).Count() > 0;

            task.DigitPlaces = criterionInfo.DigitPlaces;
            task.CriterionType = criterionInfo.CriterionType;

            var blindSubjectCode = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).Select(x=>x.BlindSubjectCode).FirstNotNullAsync();
            task.SubjectCode = blindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : blindSubjectCode;
            return task;
        }

        /// <summary>
        /// 验证阅片休息时间
        /// </summary>
        /// <returns></returns>
        private async Task VerifyReadingRestTime()
        {
            var cacheKey = _userInfo.Id.ToString();
            var value = _cache.Get(cacheKey);
            if (value == null)
            {
                _cache.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromHours(5));

            }
            else
            {
                var cacheDate = DateTime.Parse(value.ToString());
                int timespanMin = (DateTime.Now - cacheDate).Minutes;
                if (timespanMin > 120 && timespanMin < 140)
                {
                    throw new BusinessValidationFailedException("您已连续阅片两个小时,请休息一会!");
                }
                else if (timespanMin > 140)
                {
                    cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 140))) * 140);
                    _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5));

                }

            }



        }

        /// <summary>
        /// 签名提交任务修改状态
        /// </summary>
        /// <param name="visitTaskId"></param>
        /// <returns></returns>
        private async Task SubmitTaskChangeState(Guid visitTaskId)
        {
            await VerifyTaskIsSign(visitTaskId);
            await _visitTaskRepository.UpdatePartialFromQueryAsync(visitTaskId, x => new VisitTask()
            {
                ReadingTaskState = ReadingTaskState.HaveSigned,
                SignTime = DateTime.Now,
            });

            await _visitTaskRepository.SaveChangesAsync();

            // 触裁判任务
            await this.TriggerJudgeQuestion(visitTaskId);
            // 添加阅片期任务
            await this.AddReadingTask(visitTaskId);

            // 完成阅片修改状态
            //await this.FinishReadUpdateState(visitTaskId);


            await _visitTaskRepository.SaveChangesAsync();

            await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(visitTaskId);
        }


        /// <summary>
        /// 阅片期 -全局和肿瘤学任务的生成
        /// </summary>
        /// <returns></returns>
        private async Task AddReadingTask(Guid visitTaskId)
        {
            // ****** 先生成阅片期  阅片期任务阅片完成之后生成肿瘤学的  如果没有阅片期 直接生成肿瘤学 *********////
            #region 建立关系
            // 访视阅完产生 全局
            Dictionary<ModuleTypeEnum, ReadingCategory> typeChangeDic = new Dictionary<ModuleTypeEnum, ReadingCategory>();
            typeChangeDic.Add(ModuleTypeEnum.InPlanSubjectVisit, ReadingCategory.Visit);
            typeChangeDic.Add(ModuleTypeEnum.OutPlanSubjectVisit, ReadingCategory.Visit);
            //typeChange.Add(ModuleTypeEnum.Read, ReadingCategory.ReadingPeriod);
            typeChangeDic.Add(ModuleTypeEnum.Global, ReadingCategory.Global);
            typeChangeDic.Add(ModuleTypeEnum.Referee, ReadingCategory.Judge);
            typeChangeDic.Add(ModuleTypeEnum.Oncology, ReadingCategory.Oncology);
            #endregion
            var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
            List<ReadingGenerataTaskDTO> needReadList = new List<ReadingGenerataTaskDTO>();
            if (!taskInfo.IsAnalysisCreate)
            {
                // 任务类型
                switch (taskInfo.ReadingCategory)
                {
                    case ReadingCategory.Visit:
                        needReadList = await _readModuleRepository.Where(x => x.SubjectVisitId == taskInfo.SourceSubjectVisitId &&

                        x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
                        x.ReadingSetType == ReadingSetType.ImageReading)
                         .Select(x => new ReadingGenerataTaskDTO
                         {
                             IsUrgent = x.IsUrgent ?? false,
                             SubjectId = x.SubjectId,
                             VisitNum = x.SubjectVisit.VisitNum,
                             ReadingName = x.ModuleName,
                             ReadModuleId = x.Id,
                             ReadingCategory = typeChangeDic[x.ModuleType],
                         }).ToListAsync();
                        if (needReadList.Any(x => x.ReadingCategory == ReadingCategory.Global))
                        {
                            needReadList = needReadList.Where(x => x.ReadingCategory != ReadingCategory.Oncology).ToList();
                        }
                        //needReadList = needReadList.Where(x => _visitTaskRepository.Where(y => y.SouceReadModuleId == x.ReadModuleId).Count() == 0).ToList();
                        await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
                        {
                            OriginalVisitId = visitTaskId,
                            ReadingCategory = GenerateTaskCategory.Global,
                            TrialId = taskInfo.TrialId,
                            ReadingGenerataTaskList = needReadList
                        });
                        break;
                    // 肿瘤学
                    case ReadingCategory.Global:
                        var subjectVisitId = await _readModuleRepository.Where(x => x.Id == taskInfo.SouceReadModuleId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync();
                        var oncologyReadId = await _readModuleRepository.Where(x => x.SubjectVisitId == subjectVisitId && x.ModuleType == ModuleTypeEnum.Oncology
                        && x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId


                        ).Select(x => x.Id).FirstOrDefaultAsync();

                        if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskId && x.JudgeVisitTaskId == null))
                        {
                            await AddOncologyTask(oncologyReadId);
                        }


                        break;
                }
            }





        }

        #endregion


    }
}