//--------------------------------------------------------------------
//     此代码由T4模板自动生成  byzhouhang 20210918
//	   生成时间 2023-06-15 15:06:06 
//     对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------

using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Domain.Share;
using MassTransit;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.Application.Service.Reading.Interface;
using IRaCIS.Core.Application.Contracts;

namespace IRaCIS.Core.Application.Service
{
    /// <summary>
    /// 临床答案
    /// </summary>	
    [ApiExplorerSettings(GroupName = "Reading")]
    public class ClinicalAnswerService :  BaseService, IClinicalAnswerService
	{

        private readonly IRepository<TrialClinicalQuestion> _trialClinicalQuestionRepository;

        private readonly IRepository<SystemClinicalQuestion> _systemClinicalQuestionRepository;


        private readonly IRepository<SystemClinicalTableQuestion> _systemClinicalTableQuestionRepository;

        private readonly IRepository<TrialClinicalTableQuestion> _trialClinicalTableQuestionRepository;

        private readonly IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository;

		private readonly IRepository<ClinicalForm> _clinicalFormRepository;
		private readonly IRepository<Subject> _subjectRepository;
		private readonly IRepository<ReadModuleCriterionFrom> _readModuleCriterionFromRepository;
		private readonly IRepository<ReadModule> _readModuleRepository;
		private readonly IRepository<ClinicalQuestionAnswer> _clinicalQuestionAnswerRepository;

        private readonly IRepository<ClinicalTableAnswer> _clinicalTableAnswerRepository;

        private readonly IRepository<ClinicalAnswerRowInfo> _clinicalAnswerRowInfoRepository;

		private readonly IRepository<ReadingClinicalData> _readingClinicalDataRepository;
		private readonly IRepository<SubjectVisit> _subjectVisitRepository;

		private readonly IClinicalQuestionService _iClinicalQuestionService;

        private readonly IReadingClinicalDataService _iReadingClinicalDataService;


        public ClinicalAnswerService(IRepository<TrialClinicalQuestion> trialClinicalQuestionRepository,
            IRepository<SystemClinicalTableQuestion> systemClinicalTableQuestionRepository,
            IRepository<TrialClinicalTableQuestion> trialClinicalTableQuestionRepository,
			IRepository<ReadingClinicalData> readingClinicalDataRepository,
		IRepository<ClinicalForm> clinicalFormRepository,
		IRepository<Subject> subjectRepository,
        IReadingClinicalDataService iReadingClinicalDataService,
            IRepository<ReadModuleCriterionFrom> readModuleCriterionFromRepository,
			IRepository<ReadModule> readModuleRepository,
		IRepository<SubjectVisit> subjectVisitRepository,
			IRepository<ClinicalTableAnswer> clinicalTableAnswerRepository,
             IRepository<ClinicalQuestionAnswer> clinicalQuestionAnswerRepository,
                IClinicalQuestionService iClinicalQuestionService,
                IRepository<ClinicalAnswerRowInfo> clinicalAnswerRowInfoRepository,
        IRepository<ClinicalDataTrialSet> clinicalDataTrialSetRepository,
			IRepository<SystemClinicalQuestion> systemClinicalQuestionRepository
            )
        {
            _subjectVisitRepository = subjectVisitRepository;
			_readingClinicalDataRepository = readingClinicalDataRepository;
			_clinicalAnswerRowInfoRepository = clinicalAnswerRowInfoRepository;
            _clinicalQuestionAnswerRepository = clinicalQuestionAnswerRepository;
            _systemClinicalTableQuestionRepository = systemClinicalTableQuestionRepository;
            _trialClinicalQuestionRepository = trialClinicalQuestionRepository;
            _trialClinicalTableQuestionRepository = trialClinicalTableQuestionRepository;
            _systemClinicalQuestionRepository = systemClinicalQuestionRepository;
            _clinicalDataTrialSetRepository = clinicalDataTrialSetRepository;
            _iReadingClinicalDataService = iReadingClinicalDataService;
                _clinicalFormRepository = clinicalFormRepository;
			this._subjectRepository = subjectRepository;
			this._readModuleCriterionFromRepository = readModuleCriterionFromRepository;
			this._readModuleRepository = readModuleRepository;
			_clinicalTableAnswerRepository = clinicalTableAnswerRepository;
            _iClinicalQuestionService = iClinicalQuestionService;
        }

        /// <summary>
        /// CRC签名临床数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> CRCSignClinicalData(CRCSignClinicalDataInDto inDto)
        {

            await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(x =>x.Id==inDto.ReadingClinicalDataId, x => new ReadingClinicalData()
                {
                    IsSign = true,
                    ReadingClinicalDataState = ReadingClinicalDataStatus.HaveSigned
                });

            await _readingClinicalDataRepository.SaveChangesAsync();
            return ResponseOutput.Ok(true);
        }

        /// <summary>
        /// 自动添加CRC临床数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task AutoAddCRCClinical(AutoAddClinicalInDto inDto)
        {
			var dataTrialSetList = await _clinicalDataTrialSetRepository.Where(x =>x.TrialId == inDto.TrialId && x.UploadRole == UploadRole.CRC && x.IsConfirm)
			  .IgnoreAutoIncludes().ToListAsync();
            var baseLine = await _subjectVisitRepository.Where(x => x.TrialId == inDto.TrialId)
                .WhereIf(inDto.SubjectId!=null,x=>x.SubjectId==inDto.SubjectId)
			
				.Select(x => new
            {

                x.SubjectId,
                VisitId = x.Id,
                x.IsBaseLine,
            }).ToListAsync();

			var clinicalDataList =await _readingClinicalDataRepository
				   .WhereIf(inDto.SubjectId != null, x => x.SubjectId == inDto.SubjectId)
				.Where(x =>x.TrialId==inDto.TrialId&&x.ClinicalDataTrialSet.UploadRole== UploadRole.CRC)
                .Select(x=>new 
                {
                    ClinicalDataTrialSetId=x.ClinicalDataTrialSetId,
                    SubjectId=x.SubjectId,
                    x.ReadingId,

                }).ToListAsync();

            List<ReadingClinicalData> readingClinicalDatas = new List<ReadingClinicalData>();

            baseLine.Select(x => x.SubjectId).Distinct().ForEach(n =>
            {
                var baseLineVisitId = baseLine.Where(x => x.IsBaseLine && x.SubjectId == n).Select(x => x.VisitId).First();
                readingClinicalDatas.AddRange(
                    dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.Subject).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
                    .Select(x => new ReadingClinicalData()
                {
                    ClinicalDataTrialSetId = x.Id,
                    IsVisit = true,
                    SubjectId = n,
                    ReadingId = baseLineVisitId,
                    TrialId = inDto.TrialId
                }).ToList());


				readingClinicalDatas.AddRange(
				  dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.ImageRead).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
				  .Select(x => new ReadingClinicalData()
				  {
					  ClinicalDataTrialSetId = x.Id,
					  IsVisit = false,
					  SubjectId = n,
					  ReadingId = default(Guid),
					  TrialId = inDto.TrialId
				  }).ToList());

				readingClinicalDatas.AddRange(
				  dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.OncologyRead).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
				  .Select(x => new ReadingClinicalData()
				  {
					  ClinicalDataTrialSetId = x.Id,
					  IsVisit = false,
					  SubjectId = n,
					  ReadingId = default(Guid),
					  TrialId = inDto.TrialId
				  }).ToList());
			});

            baseLine.ForEach(n =>
            {
				readingClinicalDatas.AddRange(
				   dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.SubjectVisit).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.ReadingId == n.VisitId).Count() == 0)
				   .Select(x => new ReadingClinicalData()
				   {
					   ClinicalDataTrialSetId = x.Id,
					   IsVisit = true,
					   SubjectId = n.SubjectId,
					   ReadingId = n.VisitId,
					   TrialId = inDto.TrialId
				   }).ToList());
			});

          
            await _readingClinicalDataRepository.AddRangeAsync(readingClinicalDatas);
            await _readingClinicalDataRepository.SaveChangesAsync();


        }

		/// <summary>
		/// 获取CRC受试者临床数据
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
        public async Task<PageOutput<GetCRCSubjectClinicalOutDto>> GetCRCSubjectClinicalList(GetCRCSubjectClinicalInDto inDto)
        {

            //await AutoAddCRCClinical(new AutoAddClinicalInDto()
            //{
            //    TrialId = inDto.TrialId
            //}) ;

			var subjects = await _subjectRepository.Where(x => x.TrialId == inDto.TrialId).Select(x => new GetCRCSubjectClinicalResultDto()
            {
                SubjectId = x.Id,
                SubjectCode = x.Code
            }).ToListAsync();


            var clinicalData= _readingClinicalDataRepository.Where(x=>x.TrialId == inDto.TrialId&&x.ClinicalDataTrialSet.UploadRole==UploadRole.CRC&&x.ClinicalDataTrialSet.ClinicalDataLevel!= ClinicalLevel.SubjectVisit)
                .Where(x=>!x.IsSign)
                .WhereIf(inDto.SubjectId!=null,x=>x.SubjectId==inDto.SubjectId)
                .WhereIf(inDto.SubjectCode != null, x => x.Subject.Code.Contains(inDto.SubjectCode??string.Empty))
                .Where(x=> x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.Subject)
                .Include(x=>x.ClinicalDataTrialSet).Select(x=>new GetCRCSubjectClinicalOutDto() { 
                  SubjectId=x.SubjectId,
					SubjectCode=x.Subject.Code,
                    TrialId=inDto.TrialId,
					ReadingId= x.ReadingId,
                    ReadingClinicalDataId=x.Id,
					UploadRole = x.ClinicalDataTrialSet.UploadRole,
					ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel,
                    ClinicalUploadType= x.ClinicalDataTrialSet.ClinicalUploadType,
                    BaseLineVisitId= x.Subject.SubjectVisitList.Where(x=>x.IsBaseLine).Select(x=>x.Id).FirstOrDefault(),
                    ClinicalDataTrialSetId = x.ClinicalDataTrialSet.Id,
					ClinicalDataSetEnName= x.ClinicalDataTrialSet.ClinicalDataSetEnName,
					ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName,
				});

			var pageList = await clinicalData.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, string.IsNullOrWhiteSpace(inDto.SortField) ? nameof(GetCRCSubjectClinicalOutDto.SubjectCode) : inDto.SortField, inDto.Asc);
			// 一次查询报错 分两次写
			pageList.CurrentPageData.ForEach(x =>
            {
                x.ClinicalDataSetEnName = x.ClinicalDataSetName.LanguageName(x.ClinicalDataSetEnName, _userInfo.IsEn_Us);
            });
			var clinicalFormData = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId).ToListAsync();
			pageList.CurrentPageData.ForEach(n =>
			{
				n.ClinicalCount = clinicalFormData.Where(y => y.ClinicalDataTrialSetId == n.ClinicalDataTrialSetId && y.SubjectId == n.SubjectId).Count();
			});
            return pageList;
        }

        /// <summary>
        /// 获取表单列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetClinicalQuestionAnswerListOutDto> GetClinicalQuestionFormList(GetClinicalQuestionAnswerListInDto inDto)
        {
            var result = new GetClinicalQuestionAnswerListOutDto();
            result.AnswerList = new List<Dictionary<string, string>>();
            result.QuestionList=await _trialClinicalQuestionRepository.Where(x=>x.TrialClinicalId==inDto.ClinicalDataTrialSetId
            &&x.ClinicalQuestionType!= ReadingQestionType.Group
            && x.ClinicalQuestionType != ReadingQestionType.Table).OrderByDescending(x=>x.IsCheckDate).ThenBy(x=>x.ShowOrder)
               .ProjectTo<TrialClinicalQuestionDto>(_mapper.ConfigurationProvider).ToListAsync();

            var answers = await _clinicalQuestionAnswerRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ClinicalDataTrialSetId == inDto.ClinicalDataTrialSetId)
                .Select(x => new
                {
                    x.ClinicalFormId,
                    x.ClinicalForm.CheckDate,
                    x.QuestionId,
                    x.Answer
                })
                .ToListAsync();

            var ClinicalFormIds = answers.OrderBy(x=>x.CheckDate).Select(x => x.ClinicalFormId).Distinct().ToList();
            ClinicalFormIds.ForEach(x =>
            {
                var dic = answers.Where(y => y.ClinicalFormId == x).ToDictionary(x => x.QuestionId.ToString(), x => x.Answer);
                dic.Add("ClinicalFormId", x.ToString());
				dic.Add("TrialId", inDto.TrialId.ToString());
				dic.Add("SubjectId", inDto.SubjectId.ToString());
				dic.Add("ClinicalDataTrialSetId", inDto.ClinicalDataTrialSetId.ToString());
				
				result.AnswerList.Add(dic);

            });
            return result;
        }

        /// <summary>
        /// 获取临床数据表单问题
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<ClinicalQuestionPreviewDto>> GetClinicalFormInfo(GetClinicalFormInfoInDto inDto)
        {
            var formInfo = await _clinicalFormRepository.Where(x => x.Id == inDto.ClinicalFormId).FirstNotNullAsync();

            var questionAnswer = await _clinicalQuestionAnswerRepository.Where(x => x.ClinicalFormId == inDto.ClinicalFormId).Select(x => new ClinicalFormQuestionAnswer
            {
                QuestionId = x.QuestionId,
                Answer = x.Answer
            }).ToListAsync();

            var tableAnswer = await _clinicalTableAnswerRepository.Where(x => x.ClinicalFormId == inDto.ClinicalFormId).Select(x => new ClinicalFormTableQuestionAnswer
            {
                TableQuestionId = x.TableQuestionId,
                Answer = x.Answer,
                QuestionId = x.QuestionId,
                RowIndex = x.ClinicalAnswerRowInfo.RowIndex
            }).ToListAsync();

            var questions = await _trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == formInfo.ClinicalDataTrialSetId)
              .ProjectTo<ClinicalQuestionPreviewDto>(_mapper.ConfigurationProvider).ToListAsync();

            var tableQuestions = await _trialClinicalTableQuestionRepository.Where(x => x.TrialClinicalId == formInfo.ClinicalDataTrialSetId)
                .ProjectTo<ClinicalTablePreviewDto>(_mapper.ConfigurationProvider).ToListAsync();


            var result = questions.Where(x => x.ClinicalQuestionType == ReadingQestionType.Group).ToList();

            result.ForEach(x =>
            {
                _iClinicalQuestionService.FindChildQuestion(x, questions, tableQuestions, questionAnswer, tableAnswer);
            });

            return result;
        }



        /// <summary>
        /// 提交临床数据表单
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> SubmitClinicalForm(SubmitClinicalFormInDto inDto)
        {


         
            ClinicalForm clinicalForm = new ClinicalForm() { };
			clinicalForm = new ClinicalForm()
			{
				ClinicalDataTrialSetId = inDto.ClinicalDataTrialSetId,
				SubjectId = inDto.SubjectId,
                TrialId= inDto.TrialId,
				Id = inDto.ClinicalFormId ?? NewId.NextGuid(),
				ReadingId = inDto.ReadingId,
			};

            if (inDto.ClinicalFormId!=null&&(await _readModuleCriterionFromRepository.AnyAsync(x => x.ClinicalFormId == inDto.ClinicalFormId.Value)))
            {
                throw new BusinessValidationFailedException("当前表单已确认,无法修改!");
            }

            var existsClinical = await _clinicalFormRepository.Where(x =>
            x.SubjectId == inDto.SubjectId
            && x.ClinicalDataTrialSetId == inDto.ClinicalDataTrialSetId
            ).WhereIf(inDto.ReadingId != null, x => x.ReadingId == inDto.ReadingId)
            .Where(x => x.ClinicalDataTrialSet.UploadRole != UploadRole.CRC && !(x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.ImageRead
            || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.OncologyRead)).AnyAsync();

            if (existsClinical)
            {
                throw new BusinessValidationFailedException("已经添加过临床数据,不允许多次添加!");
            }
			try
            {
				var checkDateQuestionId = await _trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == inDto.ClinicalDataTrialSetId && x.IsCheckDate).Select(x => x.Id).FirstNotNullAsync();
                clinicalForm.CheckDate = DateTime.Parse(inDto.QuestionAnswers.Where(x => x.QuestionId == checkDateQuestionId).Select(x => x.Answer).First());

			}
            catch (Exception)
            {
              
            }

            if (clinicalForm.CheckDate != null)
            {
                if (await _readModuleRepository.AnyAsync(x =>x.SubjectId== inDto.SubjectId&& x.SubjectVisit.LatestScanDate <= clinicalForm.CheckDate && x.IsCRCConfirm))
                {
					throw new BusinessValidationFailedException("无法添加和修改当前日期的临床数据,因为CRC已经确认!");
				}

			}

            List<ClinicalQuestionAnswer> clinicalQuestionAnswers = inDto.QuestionAnswers.Select(x => new ClinicalQuestionAnswer()
            {
                Answer=x.Answer,
                ClinicalDataTrialSetId=inDto.ClinicalDataTrialSetId,
                SubjectId=inDto.SubjectId,
                ClinicalFormId= clinicalForm.Id,
                QuestionId=x.QuestionId,
            }).ToList();

            List<ClinicalAnswerRowInfo> clinicalAnswerRowInfos = new List<ClinicalAnswerRowInfo>();

            List<ClinicalTableAnswer> clinicalTableAnswers = new List<ClinicalTableAnswer>();

            inDto.TableQuestionAnswerList.ForEach(x => {
                var questionid = x.QuestionId;

                for (int i = 0; i < x.TableQuestionAnswers.Count(); i++)
                {
                    var rowInfo = new ClinicalAnswerRowInfo()
                    {
                        Id = NewId.NextGuid(),
                        SubjectId = inDto.SubjectId,
                        ClinicalFormId = clinicalForm.Id,
                        QuestionId = questionid,
                        RowIndex = i+1,
                    };
                    clinicalAnswerRowInfos.Add(rowInfo);

                    x.TableQuestionAnswers[i].ForEach(y => {

                        clinicalTableAnswers.Add(new ClinicalTableAnswer()
                        {
                            Answer=y.Answer,
                            ClinicalFormId= clinicalForm.Id,
                            QuestionId= questionid,
                            RowId= rowInfo.Id,
                            TableQuestionId=y.TableQuestionId,
                            SubjectId= inDto.SubjectId,
                           

                        });

                   });
                }

            });

            if (inDto.ClinicalFormId != null)
            {
                await _clinicalFormRepository.BatchDeleteNoTrackingAsync(x => x.Id == inDto.ClinicalFormId);
                await _clinicalQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
                await _clinicalAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
                await _clinicalTableAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
            }
            //if(inDto.ReadingId!=null)
            //{
            //    await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(x => x.ReadingId == inDto.ReadingId && x.ClinicalDataTrialSetId == inDto.ClinicalDataTrialSetId, x => new ReadingClinicalData()
            //    {
            //        IsSign = true
            //    });
            //}
            await _clinicalFormRepository.AddAsync(clinicalForm);
            await _clinicalQuestionAnswerRepository.AddRangeAsync(clinicalQuestionAnswers);
            await _clinicalAnswerRowInfoRepository.AddRangeAsync(clinicalAnswerRowInfos);
            await _clinicalTableAnswerRepository.AddRangeAsync(clinicalTableAnswers);
            await _clinicalTableAnswerRepository.SaveChangesAsync();
            return ResponseOutput.Ok(true);
        }

        /// <summary>
        /// 删除表单数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        [HttpPost]
        public async Task<IResponseOutput> DeleteClinicalForm(DeleteClinicalFormInDto inDto)
        {

            if (await _readModuleCriterionFromRepository.AnyAsync(x => x.ClinicalFormId == inDto.ClinicalFormId))
            {
				throw new BusinessValidationFailedException("当前表单已确认,无法删除!");
			}

			await _clinicalFormRepository.BatchDeleteNoTrackingAsync(x => x.Id == inDto.ClinicalFormId);
			await _clinicalQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
			await _clinicalAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
			await _clinicalTableAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
			return ResponseOutput.Ok(true);
		}

        /// <summary>
        /// 获取PM待确认列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<GetCRCConfirmListOutDto>> GetPMConfirmList(GetPMConfirmListInDto inDto)
        {
          return  await GetCRCConfirmList(new GetCRCConfirmListInDto()
            {
                TrialId = inDto.TrialId,
                IsCRCConfirm = true,
                IsPMConfirm = false,
                PageIndex = inDto.PageIndex,
                PageSize = inDto.PageSize,
                Asc = inDto.Asc,
                SortField = inDto.SortField,
                TrialReadingCriterionId = inDto.TrialReadingCriterionId

            });
        }

        /// <summary>
        /// 获取CRC确认列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<GetCRCConfirmListOutDto>> GetCRCConfirmList(GetCRCConfirmListInDto inDto)
        {
            if (inDto.ReadModuleId != null)
            {
                var readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
                inDto.TrialReadingCriterionId = readModule.TrialReadingCriterionId;
            }
            var query = _readModuleRepository.Where(x => x.TrialId == inDto.TrialId)
                .WhereIf(inDto.ReadModuleId != null, x => x.Id == inDto.ReadModuleId)
                .WhereIf(inDto.IsCRCConfirm != null, x => x.IsCRCConfirm == inDto.IsCRCConfirm)
                 .WhereIf(inDto.IsPMConfirm != null, x => x.IsPMConfirm == inDto.IsPMConfirm)
                .WhereIf(inDto.SubjectCode != null, x => x.Subject.Code.Contains(inDto.SubjectCode??string.Empty))
                .WhereIf(inDto.TrialReadingCriterionId != null, x => x.TrialReadingCriterionId == inDto.TrialReadingCriterionId)
				.WhereIf(inDto.SubjectId != null, x => x.SubjectId == inDto.SubjectId)
                .WhereIf(inDto.StartTime != null, x => x.SubjectVisit.LatestScanDate >= inDto.StartTime)
                .WhereIf(inDto.EndTime != null, x => x.SubjectVisit.LatestScanDate <= inDto.EndTime)
                .Select(x => new GetCRCConfirmListOutDto()
                {
                 
                    SubjectId = x.SubjectId,
                    IsNotNeedPMConfirm=x.IsNotNeedPMConfirm,
                    IsCRCConfirm = x.IsCRCConfirm,
                    IsCRCApplicationRevoke=x.IsCRCApplicationRevoke,
                    VisitBlindName=x.SubjectVisit.BlindName,
                    LatestScanDate = x.SubjectVisit.LatestScanDate,
                    ReadingSetType = x.ReadingSetType,
                    IsPMConfirm = x.IsPMConfirm,
                    SubjectCode = x.Subject.Code,
                    ReadModuleId = x.Id,
                    ModuleName=x.ModuleName,
                });


		     var result = await query.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, new string[2] { "SubjectCode asc", "LatestScanDate asc" }); 
               
			var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId)
				.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
                .WhereIf(inDto.TrialReadingCriterionId!=null, x=>x.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(y=>y.TrialReadingCriterionId== inDto.TrialReadingCriterionId))
				.Where(x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.ImageRead || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.OncologyRead)
				.Include(x=>x.ClinicalDataTrialSet)
                .Select(x => new CRCClinicalForm
				{
					SubjectId=x.SubjectId,
					CheckDate = x.CheckDate,
					ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel,
					ClinicalFormId = x.Id,
					ClinicalDataTrialSetId= x.ClinicalDataTrialSet.Id,
					ClinicalDataSetName =x.ClinicalDataTrialSet.ClinicalDataSetName,
                    ClinicalDataSetEnName=x.ClinicalDataTrialSet.ClinicalDataSetEnName,
                    IsHaveTableQuestion=x.ClinicalDataTrialSet.TrialClinicalQuestionList.Any(y=>y.ClinicalQuestionType== ReadingQestionType.Table),
				}).ToListAsync();
            var confirmList = await _readModuleCriterionFromRepository.Where(x => x.TrialId == inDto.TrialId
                &&x.ClinicalForm.ClinicalDataTrialSet.UploadRole== UploadRole.CRC
                &&(x.ClinicalForm.ClinicalDataTrialSet.ClinicalDataLevel==ClinicalLevel.ImageRead|| x.ClinicalForm.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.OncologyRead))
                .Select(x => new GetCRCBeConfirm
				{
					CheckDate = x.ClinicalForm.CheckDate ?? default(DateTime),
					ClinicalDataSetName = x.ClinicalForm.ClinicalDataTrialSet.ClinicalDataSetName,
					ClinicalDataSetEnName = x.ClinicalForm.ClinicalDataTrialSet.ClinicalDataSetEnName,
					ClinicalFormId = x.ClinicalFormId,
					ClinicalDataTrialSetId = x.ClinicalForm.ClinicalDataTrialSet.Id,
                    ReadModuleId=x.ReadModuleId,
                    IsHaveTableQuestion=x.ClinicalForm.ClinicalDataTrialSet.TrialClinicalQuestionList.Any(y => y.ClinicalQuestionType == ReadingQestionType.Table)
				}).ToListAsync();
                
             
            result.CurrentPageData.ForEach(x =>
            {
                if (x.IsCRCConfirm)
                {
                    x.ClinicalFormList = confirmList.Where(y => y.ReadModuleId == x.ReadModuleId).Select(y=>new GetCRCBeConfirmListOutDto() {
						CheckDate = y.CheckDate,
                        ClinicalDataSetName= y.ClinicalDataSetName.LanguageName(y.ClinicalDataSetEnName, _userInfo.IsEn_Us),
                        ClinicalDataSetEnName= y.ClinicalDataSetEnName,
                        ClinicalFormId=y.ClinicalFormId,
						ClinicalDataTrialSetId=y.ClinicalDataTrialSetId,
                        IsHaveTableQuestion=y.IsHaveTableQuestion,
					}).ToList();
                }
                else
                {
                    if (x.ReadingSetType == ReadingSetType.ImageReading)
                    {
                        x.ClinicalFormList = formList.Where(y => y.ClinicalDataLevel == ClinicalLevel.ImageRead&&y.CheckDate <= x.LatestScanDate&&y.SubjectId==x.SubjectId)
                     
					   .Select(y => new GetCRCBeConfirmListOutDto()
					   {
						   CheckDate = y.CheckDate ?? default(DateTime),
						   ClinicalDataSetName = y.ClinicalDataSetName.LanguageName(y.ClinicalDataSetEnName, _userInfo.IsEn_Us),
						   ClinicalDataSetEnName = y.ClinicalDataSetEnName,
						   ClinicalFormId = y.ClinicalFormId,
						   ClinicalDataTrialSetId = y.ClinicalDataTrialSetId,
						   IsHaveTableQuestion = y.IsHaveTableQuestion,
					   }).ToList();
                    }
                    else
                    {
						x.ClinicalFormList = formList.Where(y => y.ClinicalDataLevel == ClinicalLevel.OncologyRead&&y.CheckDate <= x.LatestScanDate && y.SubjectId == x.SubjectId)
                        .Select(y => new GetCRCBeConfirmListOutDto()
						{
							CheckDate = y.CheckDate ?? default(DateTime),
							ClinicalDataSetName = y.ClinicalDataSetName.LanguageName(y.ClinicalDataSetEnName, _userInfo.IsEn_Us),
							ClinicalDataSetEnName = y.ClinicalDataSetEnName,
							ClinicalFormId = y.ClinicalFormId,
							ClinicalDataTrialSetId = y.ClinicalDataTrialSetId,
							IsHaveTableQuestion = y.IsHaveTableQuestion,
						}).ToList();
					}
				}
            });
            return result;
		}

        /// <summary>
        /// 获取CRC待确认列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<GetCRCBeConfirmListOutDto>> GetCRCBeConfirmList(GetCRCBeConfirmListInDto inDto)
        {
            var result = (await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
            {
                ReadModuleId = inDto.ReadModuleId,
                TrialId = inDto.TrialId,
                PageIndex=1,
                PageSize=9999,
                
            })).CurrentPageData.SelectMany(x => x.ClinicalFormList).ToList();
            return result.OrderBy(x => x.ClinicalDataSetName).ThenBy(x => x.CheckDate).ToList();
		}


        /// <summary>
        /// 获取临床数据表格信息  查看没有表格问题的列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(List<GetClinicalTableListOutDto>,object)> GetClinicalTableList(GetClinicalTableListInDto inDto)
        {

			var readModule=await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();

			var confirmList = (await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
			{
				ReadModuleId = inDto.ReadModuleId,
				TrialId = inDto.TrialId,
				PageIndex = 1,
				PageSize = 9999,

			})).CurrentPageData.SelectMany(x => x.ClinicalFormList).ToList();

           var clinicalDataTrialSetIds  = confirmList.Select(x => x.ClinicalDataTrialSetId).Distinct().ToList();
            var clinicalFormIds = confirmList.Select(x => x.ClinicalFormId).ToList();

            var questionList = await _trialClinicalQuestionRepository.Where(x => clinicalDataTrialSetIds.Contains( x.TrialClinicalId)
			&& x.ClinicalQuestionType != ReadingQestionType.Group
			&& x.ClinicalQuestionType != ReadingQestionType.Table).OrderBy(x=>x.TrialClinicalId).ThenBy(x => x.ShowOrder)
			   .ProjectTo<TrialClinicalQuestionDto>(_mapper.ConfigurationProvider).ToListAsync();
			var answers = await _clinicalQuestionAnswerRepository.Where(x => clinicalFormIds.Contains(x.ClinicalFormId))
			.Select(x => new
			{
                x.ClinicalDataTrialSetId,
				x.ClinicalFormId,
				x.ClinicalForm.CheckDate,
				x.QuestionId,
				x.Answer
			})
			.ToListAsync();
			List<GetClinicalTableListOutDto> result = new List<GetClinicalTableListOutDto>();
            clinicalDataTrialSetIds.ForEach(x => {
                GetClinicalTableListOutDto dto = new GetClinicalTableListOutDto();
                dto.ModuleName = readModule.ModuleName;
                dto.ClinicalDataSetName = confirmList.Where(y => y.ClinicalDataTrialSetId == x).Select(y => y.ClinicalDataSetName).First();
                dto.QuestionList = questionList.Where(y => y.TrialClinicalId == x).OrderBy(y => y.ShowOrder).ToList();
                dto.AnswerList = new List<Dictionary<string, string>>();
                var ClinicalFormIds= answers.Where(y => y.ClinicalDataTrialSetId == x).OrderBy(x => x.CheckDate).Select(x => x.ClinicalFormId).Distinct().ToList();
				ClinicalFormIds.ForEach(z =>
				{
					var dic = answers.Where(y => y.ClinicalFormId == z).OrderBy(y => y.CheckDate).ToDictionary(x => x.QuestionId.ToString(), x => x.Answer);
					dic.Add("ClinicalFormId", z.ToString());
					dic.Add("TrialId", inDto.TrialId.ToString());
					dic.Add("SubjectId", readModule.SubjectId.ToString());
					dic.Add("ClinicalDataTrialSetId", x.ToString());

					dto.AnswerList.Add(dic);

				});
                result.Add(dto);
			});
            return (result, new
            {
                readModule.ModuleName,
            });

        }


        /// <summary>
        /// 获取临床数据表格信息  查看有表格问题的列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
		public async Task<(List<GetClinicalDateListOutDto>,object)> GetClinicalDateList(GetCRCBeConfirmListInDto inDto)
        {
            var readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
            var confirmList = (await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
			{
				ReadModuleId = inDto.ReadModuleId,
				TrialId = inDto.TrialId,
				PageIndex = 1,
				PageSize = 9999,

			})).CurrentPageData.SelectMany(x => x.ClinicalFormList).ToList();

			var clinicalDataTrialSetIds = confirmList.Select(x => x.ClinicalDataTrialSetId).Distinct().ToList();

            List<GetClinicalDateListOutDto> result = new List<GetClinicalDateListOutDto>();

            clinicalDataTrialSetIds.ForEach(x =>
            {

                result.Add(new GetClinicalDateListOutDto()
                {
                    ClinicalDataSetName = confirmList.Where(y => y.ClinicalDataTrialSetId == x).Select(y => y.ClinicalDataSetName).First(),
                    DateList = confirmList.Where(y => y.ClinicalDataTrialSetId == x).ToList()

                });

            });

            return (result,new  {
                readModule.ModuleName,
            });
		}

		/// <summary>
		/// CRC 确认临床数据
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
        public async Task<IResponseOutput> CRCConfirmClinical(CRCConfirmClinicalInDto inDto)
        {

            var readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
           
            var confirmlist = (await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
            {
                TrialId = inDto.TrialId,
                SubjectId= readModule.SubjectId,
                IsCRCConfirm=false,
                TrialReadingCriterionId = readModule.TrialReadingCriterionId,
                //ReadModuleId = inDto.ReadModuleId,
                PageIndex =1,
                PageSize=9999,
			})).CurrentPageData.ToList();

            var presentData = confirmlist.Where(x => x.ReadModuleId == inDto.ReadModuleId).First();

            confirmlist = confirmlist.Where(x => x.LatestScanDate <= presentData.LatestScanDate).ToList();

            await _readModuleCriterionFromRepository.BatchDeleteNoTrackingAsync(x=>x.ReadModuleId== inDto.ReadModuleId);
            List<ReadModuleCriterionFrom> needAddList = new List<ReadModuleCriterionFrom>()
            {

            };
            confirmlist.ForEach(x =>
            {
                x.ClinicalFormList.ForEach(y =>
                {
                    needAddList.Add(new ReadModuleCriterionFrom()
                    {
                        ClinicalFormId = y.ClinicalFormId,
                        ReadModuleId = x.ReadModuleId,
                        SubjectId = x.SubjectId,
                        TrialId = inDto.TrialId,
                    });
				});
            });

            foreach (var item in confirmlist)
            {
                await _readModuleRepository.UpdatePartialFromQueryAsync(x =>x.Id==item.ReadModuleId , x => new ReadModule()
                {
                    IsCRCConfirm = true,
                    IsPMConfirm=item.ClinicalFormList.Count()==0?true:false,
                    IsNotNeedPMConfirm= item.ClinicalFormList.Count() == 0 ? true : false,
                });
            }

            await _readModuleCriterionFromRepository.AddRangeAsync(needAddList);

            await _readModuleCriterionFromRepository.SaveChangesAsync();
            await _iReadingClinicalDataService.DealVisiTaskClinicalDataSignedAsync(inDto.TrialId, inDto.SubjectId, inDto.ReadModuleId, false, readModule.TrialReadingCriterionId);
            return ResponseOutput.Ok(true);
		}

        /// <summary>
        /// CRC 取消确认
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
		public async Task<IResponseOutput> CRCCancelConfirmClinical(CRCCancelConfirmClinicalInDto inDto)
        {

			var readModule = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
			var dataList = (await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
			{
				TrialId = inDto.TrialId,
				SubjectId = readModule.SubjectId,
				TrialReadingCriterionId = readModule.TrialReadingCriterionId,
				PageIndex = 1,
				PageSize = 9999,
			})).CurrentPageData;

			var presentData = dataList.Where(x => x.ReadModuleId == inDto.ReadModuleId).First();

            if (dataList.Any(x => x.IsCRCConfirm && x.LatestScanDate > presentData.LatestScanDate && x.ReadingSetType == presentData.ReadingSetType))
            {
				throw new BusinessValidationFailedException("当前数据并非最后一条确认信息,无法取消!");
			}

            if(presentData.IsPMConfirm)
            {
				throw new BusinessValidationFailedException("PM已确认,无法取消!");
			}

            if (presentData.IsNotNeedPMConfirm)
            {
                await _readModuleRepository.UpdatePartialFromQueryAsync(x => presentData.ReadModuleId == x.Id, x => new ReadModule()
                {
                    IsPMConfirm = false,
                    IsCRCConfirm = false,
                    IsNotNeedPMConfirm = false,
                });
            }
            else
            {
                await _readModuleRepository.UpdatePartialFromQueryAsync(x => presentData.ReadModuleId == x.Id, x => new ReadModule()
                {
                    IsCRCApplicationRevoke = true,
                });
            }
			

			//await _readModuleCriterionFromRepository.BatchDeleteNoTrackingAsync(x=>x.ReadModuleId== presentData.ReadModuleId);

			await _readModuleCriterionFromRepository.SaveChangesAsync();
            return ResponseOutput.Ok(true);
		}

        /// <summary>
        /// PM确认临床数据
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        [HttpPost]
        public async Task<IResponseOutput> PMConfirmClinical(CRCConfirmClinicalInDto inDto)
        {
            var readModuleData = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
            if (!readModuleData.IsCRCConfirm)
            {
				throw new BusinessValidationFailedException("CRC还未确认数据,PM无法操作");
			}

            if (readModuleData.IsCRCApplicationRevoke && inDto.IsConfirm)
            {
                throw new BusinessValidationFailedException("CRC正在申请退回,PM无法确认");
            }

            if (!readModuleData.IsCRCApplicationRevoke && !inDto.IsConfirm)
            {
                throw new BusinessValidationFailedException("CRC未申请退回,PM无法撤销");
            }

            if (inDto.IsConfirm)
            {
                await _readModuleRepository.UpdatePartialFromQueryAsync(x => inDto.ReadModuleId == x.Id, x => new ReadModule()
                {
                    IsPMConfirm = true,
                    IsClinicalDataBlind=inDto.IsClinicalDataBlind,
                    IsClinicalDataComplete=inDto.IsClinicalDataComplete,
                });
                await _readModuleRepository.SaveChangesAsync();
                await _iReadingClinicalDataService.DealVisiTaskClinicalDataSignedAsync(inDto.TrialId, inDto.SubjectId, inDto.ReadModuleId, false, readModuleData.TrialReadingCriterionId);
            }
            else
            {
                await _readModuleRepository.UpdatePartialFromQueryAsync(x => inDto.ReadModuleId == x.Id, x => new ReadModule()
                {
                    IsCRCConfirm = false,
                    IsCRCApplicationRevoke=false,
                });
                await _readModuleCriterionFromRepository.BatchDeleteNoTrackingAsync(x=>x.ReadModuleId== inDto.ReadModuleId);

                await _readModuleRepository.SaveChangesAsync();


            }
          

			

			return ResponseOutput.Ok(true);
		}

	}
}