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

using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using Panda.DynamicWebApi.Attributes;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using Microsoft.Extensions.Caching.Memory;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Infrastructure;

namespace IRaCIS.Core.Application.Service
{
	/// <summary>
	/// 阅片计算
	/// </summary>	
	
	[ApiExplorerSettings(GroupName = "Reading")]
	public class ReadingCalculateService : BaseService, IReadingCalculateService
	{
		private readonly IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository;
		private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
        private readonly IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository;
        private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<TumorAssessment> _tumorAssessmentRepository;
		private readonly IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository;

		public ReadingCalculateService(
			IRepository<ReadingTableQuestionAnswer> readingTableQuestionAnswerRepository,
			IRepository<VisitTask> visitTaskRepository,
			IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository,
			IRepository<ReadingTableQuestionTrial> readingTableQuestionTrialRepository,
			IRepository<ReadingQuestionTrial> readingQuestionTrialRepository,
			IRepository<SubjectVisit> subjectVisitRepository,
			IRepository<TumorAssessment> tumorAssessmentRepository,
			IRepository<ReadingTaskQuestionAnswer> readingTaskQuestionAnswerRepository
			)
		{
			this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository;
			this._visitTaskRepository = visitTaskRepository;
            this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
            this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository;
            this._readingQuestionTrialRepository = readingQuestionTrialRepository;
            this._subjectVisitRepository = subjectVisitRepository;
            this._tumorAssessmentRepository = tumorAssessmentRepository;
			this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository;
		}

		#region 临时对象 单个请求的生命周期 避免重复查询数据库
		
	    private List<VisitTaskAnswerInfo> visitTaskAnswerList;

		/// <summary>
		/// 获取Sod的值
		/// </summary>
		private decimal? sODData;
		#endregion

		/// <summary>
		/// 计算任务
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task CalculateTask(CalculateTaskInDto inDto) 
		{
			ReadingCalculateDto readingData = await GetReadingCalculateDto(inDto.VisitTaskId);
			readingData.IsChangeOtherTask = inDto.IsChangeOtherTask;
			await ReadingCalculate(readingData);
		}

		/// <summary>
		/// 自动计算
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task ReadingCalculate(ReadingCalculateDto inDto)
		{

			#region 计算  这里顺序非常重要 后面计算的值要依赖前面计算的结果
			var needAddList = new List<ReadingTaskQuestionAnswer>();


            List<ReadingCalculateData> calculateList = new List<ReadingCalculateData>()
            {
				//靶病灶径线之和(SOD)
				new ReadingCalculateData (){QuestionType=QuestionType.SOD,GetDecimalNullFun=GetSODData},

				//非淋巴结靶病灶长径之和
				new ReadingCalculateData (){QuestionType=QuestionType.SumOfDiameter,GetDecimalNullFun=GetSumOfDiameter},

				//与基线SOD相比变化量(mm)
			    new ReadingCalculateData (){QuestionType=QuestionType.SODChange,GetDecimalNullFun=GetSODChange},

				//与基线访视相比SOD变化百分比
			    new ReadingCalculateData (){QuestionType=QuestionType.SODPercent,GetDecimalNullFun=GetSODPercent},

				//与整个访视期间最低点相比增加的值(mm)  其他任务需要改
			    new ReadingCalculateData (){QuestionType=QuestionType.LowestIncrease,GetDecimalNullFun=GetLowestIncrease,ChangeAllTaskFun=ChangeAllLowestIncrease},
		
			    //与整个访视期间最低点相比增加的百分比   其他任务需要改
			    new ReadingCalculateData (){QuestionType=QuestionType.LowPercent,GetDecimalNullFun=GetLowPercent,ChangeAllTaskFun=ChangeAllLowPercent},

				//整个访视期间最低点访视名称            其他任务需要改
			    new ReadingCalculateData (){QuestionType=QuestionType.LowVisit,GetStringFun=GetLowVisit,ChangeAllTaskFun=ChangeAllLowVisitName},

		    	//是否存在非淋巴结靶病灶
			    new ReadingCalculateData (){QuestionType=QuestionType.IsLymphTarget,GetStringFun=GetIsLymphTarget},

			    //是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上
			    new ReadingCalculateData (){QuestionType=QuestionType.IsAddFive,GetStringFun=GetIsAddFive},

			    //被评估为NE的单个靶病灶
			    new ReadingCalculateData (){QuestionType=QuestionType.NETarget,GetStringFun=GetNETarget},

				//靶病灶评估
			    new ReadingCalculateData (){QuestionType=QuestionType.TargetLesion,GetStringFun=GetTargetLesionEvaluate},

				//非靶病灶评估
			    new ReadingCalculateData (){QuestionType=QuestionType.NoTargetLesion,GetStringFun=GetNoTargetLesionEvaluate},

				//是否存在新病灶
			    new ReadingCalculateData (){QuestionType=QuestionType.NewLesions,GetStringFun=GetNewLesionEvaluate},

			    //整体肿瘤评估
			    new ReadingCalculateData (){QuestionType=QuestionType.Tumor,GetStringFun=GetTumor},

				 //是否存在疾病
			    new ReadingCalculateData (){QuestionType=QuestionType.ExistDisease,GetStringFun=GetIsExistDisease},

			};


			var typeNAList = new List<QuestionType>
			{
				QuestionType.SODChange,
				QuestionType.SODPercent,
				QuestionType.LowestIncrease,
				QuestionType.LowPercent,
			};

            foreach (var calculate in calculateList)
            {
			   var item=inDto.QuestionInfo.FirstOrDefault(x => x.QuestionType == calculate.QuestionType);

				if (item != null)
				{
                     //计算答案  
                    if(inDto.IsOnlyChangeAllTask==false)
                    {

						#region 计算答案
						if (calculate.GetDecimalFun != null)
						{
							item.Answer = (await calculate.GetDecimalFun(inDto)).ToString();

						}
						else if (calculate.GetDecimalNullFun != null)
						{
							var value = await calculate.GetDecimalNullFun(inDto);
							if (value == null)
							{
								if (typeNAList.Contains(item.QuestionType ?? QuestionType.SOD))
								{
									item.Answer = nameof(YesOrNoOrNa.NA);
									
								}
								else
                                {
									item.Answer = string.Empty;

								}
								
							}
							else
							
							{
								item.Answer = value.ToString();
							}
						}
						else if (calculate.GetStringFun != null)
						{
							item.Answer = await calculate.GetStringFun(inDto);
						}
						#endregion
						needAddList.Add(new ReadingTaskQuestionAnswer()
						{
							Answer = item.Answer,
							ReadingQuestionTrialId = item.QuestionId,
						});
					}

					// 修改全局
					if (inDto.IsChangeOtherTask && calculate.ChangeAllTaskFun != null)
					{
						await calculate.ChangeAllTaskFun(new ChangeAllTaskDto()
						{
							calculateDto = inDto,
							QuestionId = item.QuestionId,
						});
					}

				}
            }

			decimal a = 1.1m;

			var questionIds = needAddList.Select(x => x.ReadingQuestionTrialId).ToList();

			await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => questionIds.Contains(x.ReadingQuestionTrialId) && x.VisitTaskId == inDto.VisitTaskId);
			needAddList.ForEach(x =>
			{
				x.SubjectId = inDto.SubjectId;
				x.ReadingQuestionCriterionTrialId = inDto.CriterionId;
				x.VisitTaskId = inDto.VisitTaskId;
				x.TrialId = inDto.TrialId;
				x.SubjectId = inDto.SubjectId;
			});

			await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddList);

			await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
			#endregion

			
		}


		/// <summary>
		/// 获取报告整体整体评估
		/// </summary>
		/// <param name="visitTaskId"></param>
		/// <returns></returns>
		public async Task<string> GetReportTumor(Guid visitTaskId)
		{
			return await GetTumor(await  GetReadingCalculateDto(visitTaskId));
		}

		/// <summary>
		/// 验证访视提交
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<VerifyVisitTaskQuestionsOutDto> VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
		{
	
			ReadingCalculateDto data = await GetReadingCalculateDto(inDto.VisitTaskId);
			data.IsChangeOtherTask = true;
			data.IsOnlyChangeAllTask = true;
			await ReadingCalculate(data);

			VerifyVisitTaskQuestionsOutDto result = new VerifyVisitTaskQuestionsOutDto() { 
			IsVerified=true,
			ErrorMessage=string.Empty,
			};

            List<VerifyVisitTaskDto> types = new List<VerifyVisitTaskDto>() {
                //new VerifyVisitTaskDto (){ QuestionType=QuestionType.TargetLesion,Fun=this.GetTargetLesionEvaluate },
                //new VerifyVisitTaskDto (){ QuestionType=QuestionType.NoTargetLesion,Fun=this.GetNoTargetLesionEvaluate },
                //new VerifyVisitTaskDto (){ QuestionType=QuestionType.NewLesions,Fun=this.GetNewLesionEvaluate },
			    new VerifyVisitTaskDto (){ QuestionType=QuestionType.Tumor,Fun=this.GetTumor },
			};

            foreach (var type in types)
            {
			   var question=data.QuestionInfo.Where(x => x.QuestionType == type.QuestionType).FirstOrDefault();
				if (question != null)
				{
					var calculateAnswer = await type.Fun(data);
					if (question.Answer != calculateAnswer)
					{
						result.IsVerified = false;
						var msg = $"问题【{question.QuesionName}】的答案与计算的答案不一致";
						result.ErrorMessage += result.ErrorMessage == string.Empty ? msg : "," + msg;
					}
				}
			}
			if (!result.ErrorMessage.IsNullOrEmpty())
			{
				throw new BusinessValidationFailedException(result.ErrorMessage);
			}
            return result;
		}

		/// <summary>
		/// 获取ReadingCalculateDto
		/// </summary>
		/// <param name="visitTaskId"></param>
		/// <returns></returns>
		public async Task<ReadingCalculateDto> GetReadingCalculateDto(Guid visitTaskId)
		{
			var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
			var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == (visitTask.SourceSubjectVisitId ?? default(Guid))).FirstOrDefaultAsync();

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



			var baseLinetaskId = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == baseLineVisitId && x.TaskState == TaskState.Effect && x.ArmEnum == visitTask.ArmEnum).Select(x => x.Id).FirstOrDefaultAsync();
			var criterionId = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == visitTask.TrialId && x.IsConfirm).Select(x => x.Id).FirstOrDefaultAsync();
			List<QuestionInfo> questionInfos = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == criterionId).Select(x => new QuestionInfo()
			{
				LesionType = x.LesionType,
				QuestionId = x.Id,
				QuesionName=x.QuestionName,
				QuestionType = x.QuestionType,
			}).ToListAsync();

			var questionAnswers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => new
			{
				x.ReadingQuestionTrialId,
				x.Answer
			}).ToListAsync();

			var tableQuestion = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Include(x => x.ReadingTableQuestionTrial).Select(x => new TableQuestionInfo()
			{
				Answer = x.Answer,
				QuestionMark = x.ReadingTableQuestionTrial.QuestionMark,
				TableQuestionId = x.TableQuestionId,
				QuestionId = x.QuestionId,
				
				RowIndex = x.RowIndex,
			}).ToListAsync();

			foreach (var item in questionInfos)
			{
				item.Answer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;

				var thisItemTableQuestions = tableQuestion.Where(x => x.QuestionId == item.QuestionId).ToList();

				item.TableRowInfoList = thisItemTableQuestions.GroupBy(x => new { x.RowIndex })
				   .Select(g => new TableRowInfo()
				   {
					   RowIndex = g.Key.RowIndex,
					   TableQuestionList = g.ToList()
				   }).ToList();
			}

			ReadingCalculateDto readingData = new ReadingCalculateDto()
			{
				SubjectId = visitTask.SubjectId,
				VisitTaskId = visitTaskId,
				SubjectVisitId = visitTask.SourceSubjectVisitId!.Value,
				QuestionInfo = questionInfos,
				CriterionId = criterionId,
				TrialId = visitTask.TrialId,
				IsBaseLine = subjectVisit!.IsBaseLine,
				DoctorUserId = visitTask.DoctorUserId,
				BaseLineTaskId= baseLinetaskId,
				ArmEnum=visitTask.ArmEnum,
				VisitName= subjectVisit.VisitName,
			};

			return readingData;
		}

	


		#region 获取SOD

		/// <summary>
		/// 获取SOD
		/// </summary>
		/// <remarks>
		/// 靶病灶径线之和(SOD)
		/// 非淋巴结的长径 和淋巴结的短径
		/// </remarks>
		/// <returns></returns>
		public async Task<decimal?> GetSODData(ReadingCalculateDto inDto)
		{
			if (sODData != null)
			{
				return sODData.Value;
			}

			var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList();

			if (tableQuestion.Count() == 0)
			{
				return null;
			}

			decimal result = 0;

			foreach (var item in tableQuestion)
			{
				if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph &&x.Answer.EqEnum(YesOrNoOrNa.Yes)))
				{
					// 淋巴结的短径
					result += (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0();
				}

				if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(YesOrNoOrNa.No)))
				{
					// 非淋巴结的长径
					result += item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
				}
			}

			sODData = result;

			return sODData.Value;
			


		}
		#endregion

		#region 非淋巴结靶病灶长径之和
		/// <summary>
		/// 非淋巴结靶病灶长径之和
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<decimal?> GetSumOfDiameter(ReadingCalculateDto inDto)
		{
			var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList();

			if (tableQuestion.Count() == 0)
			{
				return null;
			}

			decimal result = 0;

			foreach (var item in tableQuestion)
			{
				if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(YesOrNoOrNa.No)))
				{
					// 非淋巴结的长径
					result += item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
				}
			}


			return result;
		}
		#endregion

		#region  与基线SOD相比变化量(mm)
		/// <summary>
		/// 与基线SOD相比变化量(mm)
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<decimal?> GetSODChange(ReadingCalculateDto inDto)
		{

			var value = await GetSODData(inDto);

			if (value == null||inDto.IsBaseLine)
			{
				return null;
			}
			return value.NullChange0() - await GetBaseLineSOD(inDto);
		}
		#endregion

		#region 与整个访视期间最低点相比增加的百分比
		/// <summary>
		/// 与整个访视期间最低点相比增加的百分比
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<decimal?> GetSODPercent(ReadingCalculateDto inDto)
		{
			var thisSOD = await GetSODData(inDto);

			if (thisSOD == null||inDto.IsBaseLine)
			{
				return null;
			}

			var baseLineSOD = await GetBaseLineSOD(inDto);

			if (baseLineSOD == 0)
			{
				return 100;
			}
			else
			{
				return decimal.Round(thisSOD.NullChange0() * 100 / baseLineSOD, 2);
			}
		}
		#endregion

		#region 与整个访视期间最低点相比增加的值(mm)
		/// <summary>
		/// 与整个访视期间最低点相比增加的值(mm)
		/// </summary>
		/// <param name="inDto"></param>
		/// <remarks>
		/// 要更新之前的
		/// </remarks>
		/// <returns></returns>
		public async Task<decimal?> GetLowestIncrease(ReadingCalculateDto inDto)
		{
			var value = await GetSODData(inDto);
			if (value == null||inDto.IsBaseLine)
			{
				return null;
			}
			var decimalAnswerList = await GetVisitTaskAnswerList(inDto);
			var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault();
			return value.NullChange0() - minSOD;
		}
		#endregion

		#region 与整个访视期间最低点相比增加的百分比
		/// <summary>
		/// 与整个访视期间最低点相比增加的百分比
		/// </summary>
		/// <param name="inDto"></param>
		/// <remarks>
		/// 要更新之前的
		/// </remarks>
		/// <returns></returns>
		public async Task<decimal?> GetLowPercent(ReadingCalculateDto inDto)
		{
			var thisSOD = await GetSODData(inDto);
			if (thisSOD == null||inDto.IsBaseLine)
			{
				return null;
			}
			var decimalAnswerList = await GetVisitTaskAnswerList(inDto);
			var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault();

			if (minSOD == 0)
			{
				return 100;
			}
			else
			{
				return decimal.Round((thisSOD.NullChange0()- minSOD) * 100 / minSOD, 2);
			}


		}
		#endregion

		#region 整个访视期间最低点访视名称
		/// <summary>
		/// 整个访视期间最低点访视名称
		/// </summary>
		/// <param name="inDto"></param>
		/// <remarks>
		/// 要更新之前的
		/// </remarks>
		/// <returns></returns>
		public async Task<string> GetLowVisit(ReadingCalculateDto inDto)
		{
			if (inDto.IsBaseLine)
			{
				return nameof(YesOrNoOrNa.NA);
			}

			var decimalAnswerList = await GetVisitTaskAnswerList(inDto);
			return decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.VisitName).FirstOrDefault() ?? string.Empty;
		}
		#endregion

		#region 是否存在非淋巴结靶病灶
		/// <summary>
		/// 是否存在非淋巴结靶病灶
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<string> GetIsLymphTarget(ReadingCalculateDto inDto)
		{
			var result = IsLymph.No.GetEnumInt();
			var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList();

			foreach (var item in tableQuestion)
			{
				if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(IsLymph.Yes)))
				{
					result= IsLymph.Yes.GetEnumInt();
				}
			}

			

			return result;
		}
		#endregion

		#region 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上
		/// <summary>
		///  是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<string> GetIsAddFive(ReadingCalculateDto inDto)
		{
			if (inDto.IsBaseLine)
			{
				return YesOrNoOrNa.NA.GetEnumInt();
			}

			var LastVisitTaskId = await this.GetLastVisitTaskId(inDto);

			var questionIds = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).Select(x => x.QuestionId).ToList();
			var lastQuestionAsnwer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == LastVisitTaskId && questionIds.Contains(x.QuestionId)).Include(x=>x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
			var rowIndexs = lastQuestionAsnwer.Where(x=>x.ReadingTableQuestionTrial.QuestionMark==QuestionMark.IsLymph&& x.Answer.EqEnum(YesOrNoOrNa.Yes)).Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList();
			var thisQuestionAsnwer = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList();

			var isExists = false;
			foreach (var item in rowIndexs)
			{
				var lastValue = lastQuestionAsnwer.Where(x => x.RowIndex == item && x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();

				var thisRowData = thisQuestionAsnwer.Where(x => x.RowIndex == item).SelectMany(x => x.TableQuestionList).ToList();
				var thisValue = thisRowData.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();

				if (thisValue - lastValue > 5)
				{
					isExists = true;
				}
			}

			return isExists? YesOrNoOrNa.Yes.GetEnumInt() : YesOrNoOrNa.No.GetEnumInt();
			
		}
		#endregion

		#region 被评估为NE的单个靶病灶
		/// <summary>
		/// 被评估为NE的单个靶病灶
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<string> GetNETarget(ReadingCalculateDto inDto)
		{
			if (inDto.IsBaseLine)
			{
				return ExistOrNA.NA.GetEnumInt();
			}

			var result = inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.TargetLesion && x.Answer.EqEnum(TargetAssessment.NE));

			return result ? ExistOrNA.Exist.GetEnumInt() : ExistOrNA.NotExist.GetEnumInt();
		}
		#endregion

		#region 整体肿瘤评估

		/// <summary>
		/// 整体肿瘤评估
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<string> GetTumor(ReadingCalculateDto inDto)
		{

			if (inDto.IsBaseLine)
			{
				return OverallAssessment.NA.GetEnumInt();
			}

			var targetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.TargetLesion).Select(x => x.Answer).FirstOrDefault();
			var noTargetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NoTargetLesion).Select(x => x.Answer).FirstOrDefault();
			var newLesions = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesions).Select(x => x.Answer).FirstOrDefault();
			var result = await _tumorAssessmentRepository.Where(x => 
			x.TargetLesion == (TargetAssessment)int.Parse(targetLesion.IsNullOrEmpty()? TargetAssessment.NA.GetEnumInt(): targetLesion) && 
			x.NonTargetLesions == (NoTargetAssessment)int.Parse(noTargetLesion.IsNullOrEmpty() ? NoTargetAssessment.NA.GetEnumInt(): noTargetLesion) && 
			x.NewLesion == (NewLesionAssessment)int.Parse(newLesions.IsNullOrEmpty() ? NewLesionAssessment.NA.GetEnumInt(): newLesions)).Select(x => x.OverallEfficacy).ToListAsync();

			return result.Count == 0 ? OverallAssessment.NA.GetEnumInt() : result[0].GetEnumInt();
		}
		#endregion

		#region 是否存在疾病
		/// <summary>
		/// 是否存在疾病
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task<string> GetIsExistDisease(ReadingCalculateDto inDto)
		{
			if (!inDto.IsBaseLine)
			{
				return string.Empty;
			}
			
			var lesionCount = inDto.QuestionInfo.SelectMany(x => x.TableRowInfoList).Count();

			return lesionCount>0 ? ExistDisease.Yes.GetEnumInt() : ExistDisease.No.GetEnumInt();
		}
		#endregion


		#region 修改其他标准

		#region 修改与整个访视期间最低点相比增加的值(mm)

		/// <summary>
		/// 修改与整个访视期间最低点相比增加的值(mm)
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task ChangeAllLowestIncrease(ChangeAllTaskDto inDto)
		{
			var visitTaskList = await GetVisitTaskAnswerList(inDto.calculateDto);
			var lowSod = visitTaskList.Select(x => x.SOD).OrderBy(x => x).FirstOrDefault();
            foreach (var item in visitTaskList.Where(x=>x.VisitTaskId!=inDto.calculateDto.BaseLineTaskId))
            {
				await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == inDto.QuestionId, x => new ReadingTaskQuestionAnswer()
				{
					Answer = (item.SOD - lowSod).ToString()
				}) ;
            }
		}

		#endregion


		#region 修改整个访视期间最低点相比增加的百分比

		/// <summary>
		/// 修改整个访视期间最低点相比增加的百分比
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task ChangeAllLowPercent(ChangeAllTaskDto inDto)
		{
			var visitTaskList = await GetVisitTaskAnswerList(inDto.calculateDto);
			var lowSod = visitTaskList.Select(x => x.SOD).OrderBy(x => x).FirstOrDefault();
			foreach (var item in visitTaskList.Where(x => x.VisitTaskId != inDto.calculateDto.BaseLineTaskId))
			{
				decimal percent = 0;
				if (lowSod == 0)
				{
					percent= 100;
				}
				else
				{
					percent= decimal.Round((item.SOD - lowSod) * 100 / lowSod, 2);
				}

				await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == inDto.QuestionId, x => new ReadingTaskQuestionAnswer()
				{
					Answer = percent.ToString()
				});
			}
		}

		#endregion

		#region 修改最低方式点名称
		/// <summary>
		/// 修改最低方式点名称
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		public async Task ChangeAllLowVisitName(ChangeAllTaskDto inDto)
		{
			// 找到所有访视任务的Id

			var visitTaskIds = await _visitTaskRepository.Where(x => !x.IsAnalysisCreate && x.ReadingCategory == ReadingCategory.Visit &&
			  x.TaskState == TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.DoctorUserId == inDto.calculateDto.DoctorUserId).Select(x => x.Id).ToListAsync();

			var answer = (await GetLowVisit(inDto.calculateDto)).ToString();
		    visitTaskIds = visitTaskIds.Where(x => x != inDto.calculateDto.BaseLineTaskId).ToList();
			await this.ChangeAllVisitTaskAnswer(visitTaskIds, inDto.QuestionId, answer);

		}
		#endregion


		#endregion

		#region 通用方法

		#region 修改所有访视任务的答案
		/// <summary>
		/// 修改所有访视任务的答案
		/// </summary>
		/// <param name="visitTaskGuids"></param>
		/// <param name="questionId"></param>
		/// <param name="answer"></param>
		/// <returns></returns>
		private async Task ChangeAllVisitTaskAnswer(List<Guid> visitTaskGuids, Guid questionId, string answer)
		{
			await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => visitTaskGuids.Contains(x.VisitTaskId) && x.ReadingQuestionTrialId == questionId, x => new ReadingTaskQuestionAnswer()
			{
				Answer = answer
			});
		}
		#endregion


		#region 获取基线SOD
		/// <summary>
		/// 获取基线SOD
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		private async Task<decimal> GetBaseLineSOD(ReadingCalculateDto inDto)
		{
			if (await _visitTaskRepository.AnyAsync(x => x.Id == inDto.VisitTaskId && x.SourceSubjectVisit.IsBaseLine&&!x.IsAnalysisCreate&&x.DoctorUserId==inDto.DoctorUserId))
			{
				return 0;
			}

			// 先找到基线的任务
			var baseLineTaskId = await _visitTaskRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ReadingCategory == ReadingCategory.Visit
																  && x.SourceSubjectVisit.IsBaseLine && x.TaskState == TaskState.Effect&&!x.IsAnalysisCreate&&x.DoctorUserId==inDto.DoctorUserId)
																   .Select(x => x.Id).FirstOrDefaultAsync();


			var baseLineSOD =(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0();
			return baseLineSOD;
		}
        #endregion

        #region 获取访视任务信息
        /// <summary>
        /// 获取访视任务信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<List<VisitTaskAnswerInfo>> GetVisitTaskAnswerList(ReadingCalculateDto inDto)
        {
            if (visitTaskAnswerList == null)
            {
				// 查询的时候要把自己排除 因为查询出来的可能不是计算出的最新的
                visitTaskAnswerList = await _readingTaskQuestionAnswerRepository.Where(x =>x.VisitTaskId!=inDto.VisitTaskId&&x.VisitTask.ReadingCategory == ReadingCategory.Visit
                && x.SubjectId == inDto.SubjectId && x.VisitTask.ReadingTaskState == ReadingTaskState.HaveSigned &&x.VisitTask.ArmEnum==inDto.ArmEnum&& x.VisitTask.TaskState == TaskState.Effect && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD)
                .Select(x => new VisitTaskAnswerInfo
                {
                    VisitTaskId = x.VisitTaskId,
                    QuestionId = x.ReadingQuestionTrialId,
                    VisitName = x.VisitTask.SourceSubjectVisit.VisitName,
                    SOD = x.Answer.IsNullOrEmptyReturn0(),
                }).ToListAsync();

				// 这里是需要加上自己的 基线不用管
				if (visitTaskAnswerList.Count > 0)
				{
					visitTaskAnswerList.Add(new VisitTaskAnswerInfo()
					{
						VisitTaskId = inDto.VisitTaskId,
						QuestionId= visitTaskAnswerList[0].QuestionId,
						VisitName=inDto.VisitName,
						SOD=(await GetSODData(inDto)).ToString().IsNullOrEmptyReturn0(),
					});
				}
				

			}

            return visitTaskAnswerList;
        }
        #endregion

        /// <summary>
        /// 获取上一个访视任务Id
        /// </summary>
        /// <returns></returns>
        private async Task<Guid> GetLastVisitTaskId(ReadingCalculateDto inDto)
		{
			// 拿到这一个访视
			var thisNum = await _subjectVisitRepository.Where(x => x.Id == inDto.SubjectVisitId).Select(x => x.VisitNum).FirstOrDefaultAsync();

			// 先找到上一个访视
			var lastVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == inDto.SubjectId && !x.IsLostVisit && x.VisitNum < thisNum).OrderByDescending(x => x.VisitNum).Select(x => x.Id).FirstOrDefaultAsync();

			// 找到访视任务Id

			var LastVisitTaskId = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && x.TaskState == TaskState.Effect && !x.IsAnalysisCreate && x.SourceSubjectVisitId == lastVisitId&&x.DoctorUserId==inDto.DoctorUserId).Select(x => x.Id).FirstOrDefaultAsync();

			return LastVisitTaskId;
		}
        #endregion

        #region 计算阅片问题  外层问题

        #region 获取靶病灶评估
        /// <summary>
        /// 获取靶病灶评估
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<string> GetTargetLesionEvaluate(ReadingCalculateDto inDto)
        {
            var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList();
			if (inDto.IsBaseLine)
			{
				return TargetAssessment.NA.GetEnumInt();
			}
			if (tableQuestion.Count() == 0)
			{
				return string.Empty;
			}
			TargetLesionCalculateDto resultData = new TargetLesionCalculateDto()
			{
				//非淋巴结靶病灶长径之和  decimal
				SumOfDiameter = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SumOfDiameter).Sum(x => x.Answer.IsNullOrEmptyReturn0()),

				//所有淋巴结靶病灶的短径小于10mm bool
				DiameterLessThan10 = true,

				// SOD变化百分比
				SODPercent = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SODPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()),

				// SOD 百分比与基线期SOD相比减小≥30% bool
				SODPercentBigger30 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SODPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= 30,

				// SOD 百分比 与基线期SOD相比减小<30% bool
				SODPercentLess30 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SODPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) < 30,

				// SOD 百分比 整体访视期间最低点SOD相比增加<20%
				LowPercentLess20 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) <20,

				// SOD 百分比  比整体访视期间最低点SOD增加≥20%
				LowPercentBigger20 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= 20,

				// SOD 变化值 比整体访视期间最低点SOD绝对增加值<5 mm
				LowChangeLess5 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowestIncrease).Sum(x => x.Answer.IsNullOrEmptyReturn0()) < 5,

				// 比整体访视期间最低点SOD绝对增加值≥5 mm
				LowChangeBigger5 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowestIncrease).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= 5,

				//  被评估为NE的单个靶病灶   是否存在状态为不可评估的靶病灶
				ExixtsNETargetLesion = tableQuestion.SelectMany(x => x.TableQuestionList).Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(TargetState.UnableEvaluate)),

				//// 上次访视点整体肿瘤评估
				LastTargetLesionEvaluate = string.Empty,

				// 当前访视点非淋巴结病灶长径>0
				CurrentMajoreBigger0 = true,

                // 至少一个淋巴结靶病灶短径≥10 mm
                CurrenShortBigger10 = true,

                // 该淋巴结靶病灶短径绝对增加值≥5 mm
                IsAddFive = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.IsAddFive && x.Answer.EqEnum(YesOrNoOrNa.Yes)).Count() > 0,
            };




            foreach (var item in tableQuestion)
            {
                if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && x.Answer.EqEnum(YesOrNoOrNa.Yes)))
                {
                    // 淋巴结的短径
                    resultData.DiameterLessThan10 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() < 10;

                    // 至少一个淋巴结靶病灶短径≥10 mm
                    resultData.CurrenShortBigger10 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() >= 10;
                }

                if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && !x.Answer.EqEnum(YesOrNoOrNa.Yes)))
                {
                    // 当前访视点非淋巴结病灶
                    resultData.CurrentMajoreBigger0 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() > 0;
                }
            }


            var lastVisitTaskId = await GetLastVisitTaskId(inDto);
            var questionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.Tumor).Select(x => x.QuestionId).FirstOrDefault();
			resultData.LastTargetLesionEvaluate=(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastVisitTaskId && x.ReadingQuestionTrialId == questionId)
                .Select(x => x.Answer).FirstOrDefaultAsync()) ?? string.Empty;





			TargetAssessment result = TargetAssessment.NA;
            if (resultData.SumOfDiameter == 0 && resultData.DiameterLessThan10 && !resultData.ExixtsNETargetLesion)
            {
                result = TargetAssessment.CR;
            }
            else if (
                (resultData.SODPercentBigger30 && resultData.LowPercentLess20 && !resultData.ExixtsNETargetLesion)
                ||
                (resultData.SODPercentBigger30 && resultData.LowChangeLess5 && !resultData.ExixtsNETargetLesion)
                )
            {
                result = TargetAssessment.PR;
            }
            else if (
                (resultData.SODPercentLess30 && resultData.LowPercentLess20 && !resultData.ExixtsNETargetLesion)
                ||
                (resultData.SODPercentLess30 && resultData.LowChangeLess5 && !resultData.ExixtsNETargetLesion)
                )
            {
                result = TargetAssessment.SD;
            }
            else if (resultData.LowPercentBigger20 && resultData.LowChangeBigger5)
            {
                result = TargetAssessment.PD;
            }
            else if (
                (resultData.LowPercentLess20 && resultData.ExixtsNETargetLesion)
                ||
                (resultData.LowPercentBigger20 && resultData.LowChangeLess5 && resultData.ExixtsNETargetLesion)
                )
            {
                result = TargetAssessment.NE;
            }

            else if (!resultData.ExixtsNETargetLesion&& resultData.SumOfDiameter==0&& resultData.SODPercent == 0)
            {
                result = TargetAssessment.ND;
            }

            else if (
                (resultData.LastTargetLesionEvaluate.EqEnum(TargetAssessment.CR) && resultData.CurrenShortBigger10 && resultData.IsAddFive)
                ||
                (resultData.LastTargetLesionEvaluate.EqEnum(TargetAssessment.CR) && resultData.CurrentMajoreBigger0)
                )
            {
                result = TargetAssessment.PD;
            }


            return result.GetEnumInt();
        }
        #endregion

        #region 获取非靶病灶评估

        /// <summary>
        /// 获取非靶病灶评估
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<string> GetNoTargetLesionEvaluate(ReadingCalculateDto inDto)
        {

			NoTargetAssessment result = NoTargetAssessment.NA;

			if (inDto.IsBaseLine)
			{
				return result.GetEnumInt();
			}

			var tableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NonTargetLesions).SelectMany(x => x.TableRowInfoList).ToList();

            var tableQuestions = tableRows.SelectMany(x => x.TableQuestionList).ToList();

			//任意单个病灶 / 病灶组评估为“显著增大”
			if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NoTargetState.Increase)))
            {
				result = NoTargetAssessment.PD;
            }
            //所有单个病灶/病灶组状态评估状态为“消失”
            else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NoTargetState.Loss) ))
            {
				result = NoTargetAssessment.PD;
			}
            // 任意单个病灶/病灶组评估为“无法评估”并且没有“显著增大”
            else if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NoTargetState.Increase)) &&
                !tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && !x.Answer.EqEnum(NoTargetState.Increase) )
                )
            {
				result = NoTargetAssessment.NE;
			}
            // 基线时没有非靶病灶
            else if (tableQuestions.Count() == 0)
            {
				result = NoTargetAssessment.ND;
			}

            // 所有单个病灶/病灶组评估为”存在”或者有些评估为“消失”有些评估为“存在”,且没有“显著增大”和“无法评估”的病灶

            else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && !x.Answer.EqEnum(NoTargetState.Exist))
                || (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NoTargetState.Exist) || x.Answer.EqEnum(NoTargetState.Loss)) && !tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && (x.Answer != "显著增大" || x.Answer != "无法评估")))

                )
            {
				result = NoTargetAssessment.NN;
			}
            else
            {
                return string.Empty;
            }

			return result.GetEnumInt();

		}

        #endregion

        #region 获取新病灶评估
        /// <summary>
        ///  获取新病灶评估
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<string> GetNewLesionEvaluate(ReadingCalculateDto inDto)
        {

			NewLesionAssessment result = NewLesionAssessment.NA;
			if (inDto.IsBaseLine)
			{
				return result.GetEnumInt();
			}

			var tableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NewLesions).SelectMany(x => x.TableRowInfoList).ToList();

            var tableQuestions = tableRows.SelectMany(x => x.TableQuestionList).ToList();

			

			// 当前访视存在至少一个明确新病灶
			if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NewLesionState.Exist)))
            {
				result= NewLesionAssessment.Yes;
            }
            //当前访视不存在明确新病灶且存在至少一个疑似新病灶
            else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && !x.Answer.EqEnum(NewLesionState.Exist)) ||
                tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NewLesionState.Suspected))
                )
            {
				result = NewLesionAssessment.Suspected;
            }

            //只要有任何一个新病灶状态为“无法评估”
            else if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer.EqEnum(NewLesionState.UnableEvaluate)))
            {
				result = NewLesionAssessment.NE;
            }
            else
            {
				result = NewLesionAssessment.No;
            }
			return result.GetEnumInt();

		}
        #endregion

        #endregion

    }
}