using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Contracts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Domain.Share;
using EasyCaching.Core;
using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Auth;
using Panda.DynamicWebApi.Attributes;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using MassTransit;
using IRaCIS.Core.Application.Filter;
using static IRaCIS.Core.Domain.Share.StaticData;

namespace IRaCIS.Core.Application
{
    [ApiExplorerSettings(GroupName = "Trial")]
    public class TrialConfigService : BaseService, ITrialConfigService
    {
        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<TrialQCQuestion> _trialQCQuestionRepository;
        private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
        private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository;
        private readonly IRepository<TrialCriterionDictionaryCode> _trialCriterionDictionaryCode;
        private readonly IRepository<SystemCriterionDictionaryCode> _systemCriterionDictionaryCode;
        private readonly IRepository<ReadingQuestionCriterionSystem> _readingQuestionCriterionSystemRepository;
        private readonly IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository;
        private readonly IRepository<ReadingCriterionPage> _readingCriterionPageRepository;
        private readonly IEasyCachingProvider _provider;
        private readonly IOrganInfoService _iOrganInfoService;
        private readonly IRepository<TaskAllocationRule> _taskAllocationRuleRepository;
        private readonly IRepository<ReadingCriterionDictionary> _readingCriterionDictionaryRepository;
        private readonly IReadingQuestionService iReadingQuestionService;


        private readonly IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswer;

        private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository;
        private readonly IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository;

        private readonly IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository;

        public TrialConfigService(IRepository<Trial> trialRepository,
            IRepository<TrialQCQuestion> trialQCQuestionRepository,
            IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository,
            IRepository<ReadingQuestionTrial> readingQuestionTrialRepository,
             IRepository<TrialCriterionDictionaryCode> trialCriterionDictionaryCode,
               IRepository<SystemCriterionDictionaryCode> systemCriterionDictionaryCode,
              IRepository<ReadingQuestionCriterionSystem> readingQuestionCriterionSystemRepository,
            IRepository<ClinicalDataTrialSet> clinicalDataTrialSetRepository,
            IRepository<ReadingCriterionPage> readingCriterionPageRepository,
            IRepository<TaskAllocationRule> taskAllocationRuleRepository,
            IRepository<ReadingCriterionDictionary> readingCriterionDictionaryRepository,
            IReadingQuestionService iReadingQuestionService,
            IEasyCachingProvider provider,
            IOrganInfoService iOrganInfoService,

              IRepository<VisitTask> visitTaskRepository,
                IRepository<ReadingTableQuestionTrial> readingTableQuestionTrialRepository,
               IRepository<ReadingTableQuestionAnswer> readingTableQuestionAnswerRepository,
                 IRepository<ReadingTableAnswerRowInfo> readingTableAnswerRowInfoRepository,
            IRepository<ReadingTaskQuestionAnswer> readingTaskQuestionAnswer

            )
        {
            _trialRepository = trialRepository;
            _taskAllocationRuleRepository = taskAllocationRuleRepository;
            this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository;
            this.iReadingQuestionService = iReadingQuestionService;
            this._trialQCQuestionRepository = trialQCQuestionRepository;
            this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
            this._readingQuestionTrialRepository = readingQuestionTrialRepository;
            this._trialCriterionDictionaryCode = trialCriterionDictionaryCode;
            this._systemCriterionDictionaryCode = systemCriterionDictionaryCode;
            this._readingQuestionCriterionSystemRepository = readingQuestionCriterionSystemRepository;
            this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository;
            this._provider = provider;
            this._iOrganInfoService = iOrganInfoService;
            this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository;
            this._readingCriterionPageRepository = readingCriterionPageRepository;

            this._visitTaskRepository = visitTaskRepository;
            this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository;
            this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository;
            this._readingTaskQuestionAnswer = readingTaskQuestionAnswer;
        }


        /// <summary>
        /// 阅片信息签名验证接口
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        [HttpPost]
        public async Task<IResponseOutput> TrialReadingInfoSignVerify(TrialReadingInfoSignInDto inDto)
        {
            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync();
            var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None)
                .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null)
                .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null)
                .AnyAsync();

            if (existsJudge && trialCriterion.IsArbitrationReading)
            {
                throw new BusinessValidationFailedException("有裁判问题未配置产生裁判阅片任务的条件,操作失败！");
            }

            return ResponseOutput.Ok(true);
        }

        /// <summary>
        /// 获取项目已经确认的标准
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<GetTrialConfirmCriterionOutDto>> GetTrialConfirmCriterionList(GetTrialConfirmCriterionListInDto inDto)
        {
            List<GetTrialConfirmCriterionOutDto> result = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm)
                .Select(x => new GetTrialConfirmCriterionOutDto()
                {
                    TrialCriterionId = x.Id,
                    CriterionName = x.CriterionName
                }).ToListAsync();

            return result;
        }

        /// <summary>
        /// 阅片信息签名
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [NonDynamicMethod]
        public async Task<IResponseOutput> TrialReadingInfoSign(TrialReadingInfoSignInDto inDto)
        {
            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync();

            var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None)
                  .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null)
                 .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null)
                 .AnyAsync();

            if (existsJudge && trialCriterion.IsArbitrationReading)
            {
                throw new BusinessValidationFailedException("有裁判问题未配置产生裁判阅片任务的条件,操作失败！");
            }

            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
            {
                IsSigned = true,
                ReadingInfoSignTime = DateTime.Now
            });

            var result = await _trialRepository.SaveChangesAsync();

            return ResponseOutput.Ok(result);
        }

        /// <summary>
        /// 获取项目阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetTrialReadingInfoOutDto> GetCriterionReadingInfo(GetTrialReadingInfoInDto inDto)
        {



            GetTrialReadingInfoOutDto trialInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).ProjectTo<GetTrialReadingInfoOutDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();

            if (trialInfo.ReadingTool == null)
            {
                trialInfo.ReadingTool = ReadingTool.Dicom;
            }

            return trialInfo;
        }

        /// <summary>
        /// 同步项目标准字典信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> AsyncTrialCriterionDictionary(AsyncTrialCriterionDictionaryInDto inDto)
        {
            var trialCriterion = await _readingQuestionCriterionTrialRepository.FindAsync(inDto.TrialReadingCriterionId);

            if (trialCriterion.ReadingQuestionCriterionSystemId != null)
            {


                if (trialCriterion.SynchronizeOriginalTime == null)
                {
                    // 同步器官
                    await _iOrganInfoService.SynchronizeSystemOrganToTrial(new SynchronizeSystemOrganToTrialInDto()
                    {
                        TrialReadingCriterionId = inDto.TrialReadingCriterionId,
                        SystemCriterionId = trialCriterion.ReadingQuestionCriterionSystemId
                    });

                    // 同步问题
                    await iReadingQuestionService.SynchronizeCriterion(new SynchronizeCriterionInDto()
                    {

                        TrialReadingCriterionId = inDto.TrialReadingCriterionId,
                    });

                    // 同步字典
                    #region 同步字典



                    await _trialCriterionDictionaryCode.BatchDeleteNoTrackingAsync(x => x.TrialCriterionId == trialCriterion.Id);
                    await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == trialCriterion.Id);

                    var criterionDictionaryCodeList = await _systemCriterionDictionaryCode.Where(x => x.SystemCriterionId == trialCriterion.ReadingQuestionCriterionSystemId.Value)
                       .Select(x => new TrialCriterionDictionaryCode()
                       {
                           Code = x.Code,
                           TrialCriterionId = trialCriterion.Id,
                       }).ToListAsync();

                    criterionDictionaryCodeList.ForEach(x =>
                    {
                        x.Id = NewId.NextGuid();
                    });


                    var criterionDictionaryList = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == trialCriterion.ReadingQuestionCriterionSystemId.Value)
                       .ToListAsync();
                    criterionDictionaryList.ForEach(x =>
                    {
                        x.Id = NewId.NextGuid();
                        x.Dictionary = null;
                        x.IsSystemCriterion = false;
                        x.CriterionId = inDto.TrialReadingCriterionId;
                    });
                    await _readingCriterionDictionaryRepository.AddRangeAsync(criterionDictionaryList);

                    await _trialCriterionDictionaryCode.AddRangeAsync(criterionDictionaryCodeList);
                    #endregion



                    var systemCriterion = await _readingQuestionCriterionSystemRepository.Where(x => x.Id == trialCriterion.ReadingQuestionCriterionSystemId).FirstNotNullAsync();

                    await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
                    {
                        IsOncologyReading = systemCriterion.IsOncologyReading,
                        IseCRFShowInDicomReading = systemCriterion.IseCRFShowInDicomReading,
                    });


                    await _readingCriterionDictionaryRepository.SaveChangesAsync();
                    // 清除多余答案   -- 
                    var questionQuery = _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).AsQueryable();
                    var tableQuestionQuery = _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == inDto.TrialReadingCriterionId).AsQueryable();


                    await _readingTaskQuestionAnswer.BatchDeleteNoTrackingAsync(x => x.VisitTask.TrialReadingCriterionId == inDto.TrialReadingCriterionId && x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && questionQuery.Count(y => y.Id == x.ReadingQuestionTrialId) == 0);
                    await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTask.TrialReadingCriterionId == inDto.TrialReadingCriterionId && x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && questionQuery.Count(y => y.Id == x.QuestionId) == 0);
                    await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTask.TrialReadingCriterionId == inDto.TrialReadingCriterionId && x.ReadingQuestionTrial.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.ReadingTableQuestionTrial.TrialCriterionId == inDto.TrialReadingCriterionId && tableQuestionQuery.Count(y => y.Id == x.TableQuestionId) == 0);


                }


                await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
                {
                    SynchronizeOriginalTime = DateTime.Now
                });

                await _readingCriterionDictionaryRepository.SaveChangesAsync();



            }

            return ResponseOutput.Ok(true);
        }

        /// <summary>
        /// 修改全局阅片配置信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SetGlobalReadingInfo(SetGlobalReadingInfoInDto inDto)
        {

            //await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
            //{
            //    IsGlobalReading = inDto.IsGlobalReading

            //});
            await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.GlobalAssess);
            await _readingCriterionDictionaryRepository.AddRangeAsync(inDto.GlobalAssessList.Select(x => new ReadingCriterionDictionary
            {
                CriterionId = inDto.TrialReadingCriterionId,
                DictionaryId = x.DictionaryId,
                IsBaseLineUse = x.IsBaseLineUse,
                IsFollowVisitUse = x.IsFollowVisitUse,
                IsSystemCriterion = false,
                ParentCode = ReadingCommon.CriterionDictionary.GlobalAssess
            }));

            var result = await _readingCriterionDictionaryRepository.SaveChangesAsync();

            return ResponseOutput.Ok(result);
        }

        /// <summary>
        /// 获取全局阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetGlobalReadingOutDto> GetGlobalReadingInfo(GetOncologySetInDto inDto)
        {

            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync();
            GetGlobalReadingOutDto result = new GetGlobalReadingOutDto()
            {
                IsGlobalReading = trialCriterion.IsGlobalReading,
                IsSystemCriterion = trialCriterion.ReadingQuestionCriterionSystemId != null,
                IsSign = trialCriterion.IsSigned,
                GlobalAssessTypes = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialReadingCriterionId
            && x.ParentCode == ReadingCommon.CriterionDictionary.GlobalAssess
            )
            .Select(x => new CriterionDictionaryInfo()
            {
                Id = x.Id,
                DictionaryId = x.DictionaryId,
                ChildGroup = x.Dictionary.ChildGroup,
                IsBaseLineUse = x.IsBaseLineUse,
                IsFollowVisitUse = x.IsFollowVisitUse,
                Code = x.Dictionary.Code,
                Description = x.Dictionary.Description,
                ShowOrder = x.Dictionary.ShowOrder,
                ParentCode = x.Dictionary.Parent.Code,
                Value = x.Dictionary.Value,
                ValueCN = x.Dictionary.ValueCN
            }).OrderBy(x => x.ParentCode).ThenBy(x => x.ShowOrder).ToListAsync()
            };
            return result;
        }

        /// <summary>
        /// 获取项目肿瘤学配置
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<GetOncologySetOutDto> GetOncologySet(GetOncologySetInDto inDto)
        {

            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync();
            return new GetOncologySetOutDto
            {
                EvaluationReason = trialCriterion.EvaluationReason.IsNullOrEmpty() ? ReadingCommon.EvaluationReason : trialCriterion.EvaluationReason,
                OncologyAssessIds = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.OncologyAssess).Select(x => x.DictionaryId).ToListAsync(),
                IsSystemCriterion = trialCriterion.ReadingQuestionCriterionSystemId != null,
                IsSign = trialCriterion.IsSigned,
            };
        }

        /// <summary>
        /// 设置项目肿瘤学配置
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SetOncologySet(SetOncologySetInDto inDto)
        {


            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
            {
                EvaluationResult = inDto.EvaluationResult,
                EvaluationReason = inDto.EvaluationReason,
                IsShowDetail = inDto.IsShowDetail,

            });

            await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.OncologyAssess);

            await _readingCriterionDictionaryRepository.AddRangeAsync(inDto.OncologyAssessIds.Select(x => new ReadingCriterionDictionary
            {
                CriterionId = inDto.TrialReadingCriterionId,
                DictionaryId = x,
                IsSystemCriterion = false,
                ParentCode = ReadingCommon.CriterionDictionary.OncologyAssess
            }));

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

        /// <summary>
        /// 获取项目裁判信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(List<TrialJudgeQuestion>, object)> GetTrialReadingJudgeList(GetTrialReadingInfoInDto inDto)
        {
            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync();

            var judgeQuestionList = await _readingQuestionTrialRepository
                .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null)
                 .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null)
                .Where(x => x.ReadingQuestionCriterionTrial.IsConfirm && x.IsJudgeQuestion && x.TrialId == inDto.TrialId && x.ReadingQuestionCriterionTrialId == trialCriterion.Id)
              .Select(x => new TrialJudgeQuestion()
              {
                  AnswerCombination = x.AnswerCombination,
                  AnswerGroup = x.AnswerGroup,
                  JudgeType = x.JudgeType,
                  QuestionId = x.Id,
                  PageName = x.ReadingCriterionPage.PageName,
                  QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
                  ReadingQuestionCriterionTrialId = x.ReadingQuestionCriterionTrialId
              }).ToListAsync();



            return (judgeQuestionList, new
            {

                IsSign = trialCriterion.IsSigned,

            });
        }

        /// <summary>
        /// 获取项目标准分页信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<ReadingCriterionPageDto>> GetReadingCriterionPageList(GetTrialReadingInfoInDto inDto)
        {
            return await _readingCriterionPageRepository.Where(x => x.TrialId == inDto.TrialId).ProjectTo<ReadingCriterionPageDto>(_mapper.ConfigurationProvider).ToListAsync();
        }

        /// <summary>
        /// 获取项目阅片标准信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<(GetTrialReadingCriterionInfoOutDto, bool)> GetTrialReadingCriterionInfo(GetTrialReadingInfoInDto inDto)
        {
            GetTrialReadingCriterionInfoOutDto result = new GetTrialReadingCriterionInfoOutDto();
            result.ReadingCriterionPageList = await _readingCriterionPageRepository.Where(x => x.TrialId == inDto.TrialId).ProjectTo<ReadingCriterionPageDto>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();
            var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync();
            result.ReadingInfoSignTime = trialCriterion.ReadingInfoSignTime;

            result.DigitPlaces = trialCriterion.DigitPlaces;
            result.TrialCriterionId = trialCriterion.Id;
            result.FormType = trialCriterion.FormType;
            result.IsFromSystem = trialCriterion.ReadingQuestionCriterionSystemId != null;
            result.IsMustGlobalReading = trialCriterion.IsMustGlobalReading;
            result.IsSystemCriterion = trialCriterion.ReadingQuestionCriterionSystemId != null;


            result.TrialQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrial.IsConfirm && x.TrialId == inDto.TrialId && x.ReadingQuestionCriterionTrialId == result.TrialCriterionId
            && x.ReadingCriterionPageId == null)
              .ProjectTo<TrialReadQuestion>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();

            return (result, true);
        }




        /// <summary>
        /// 设置项目阅片标准
        /// </summary>
        /// <returns></returns>
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SetTrialReadingCriterion(SetTrialReadingCriterionInDto inDto)
        {
            if (inDto.IsSignSave)
            {
                var criterionFormType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.FormType).FirstOrDefaultAsync();
                var count = _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId)
             .WhereIf(criterionFormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null)
             .WhereIf(criterionFormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null).Count();

                if (count == 0)
                {
                    throw new BusinessValidationFailedException("当前标准下未配置问题");
                }
            }

            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
            {
                FormType = inDto.FormType,
            });




            var result = await _trialRepository.SaveChangesAsync();


            return ResponseOutput.Ok(result);
        }

        /// <summary>
        /// 设置项目阅片信息
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> SetCriterionReadingInfo(SetCriterionReadingInfoInDto inDto)
        {
            ArbitrationRule arbitration = ArbitrationRule.NA;

            if (inDto.IsArbitrationReading)
            {
                arbitration = inDto.IsReadingPeriod ? ArbitrationRule.Reading : ArbitrationRule.Visit;
            }

            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
            {
                ReadingTool = inDto.ReadingTool,
                IsReadingPeriod = inDto.IsReadingPeriod,
                //DigitPlaces=inDto.DigitPlaces,
                IsReadingTaskViewInOrder = inDto.IsReadingTaskViewInOrder,
                ReadingTaskViewEnum = inDto.ReadingTaskViewEnum,
                DigitPlaces = inDto.DigitPlaces,
                //IsImageIabeled = inDto.IsImageIabeled,
                IsReadingShowSubjectInfo = inDto.IsReadingShowSubjectInfo,
                IsReadingShowPreviousResults = inDto.IsReadingShowPreviousResults,
                GlobalUpdateType = inDto.GlobalUpdateType,
                ImagePlatform = inDto.ImagePlatform,
                IseCRFShowInDicomReading = inDto.IseCRFShowInDicomReading,
                ArbitrationRule = arbitration,
                ReadingType = inDto.ReadingType,
                IsGlobalReading = inDto.IsGlobalReading,
                IsArbitrationReading = inDto.IsArbitrationReading,
                IsOncologyReading = inDto.IsOncologyReading,


            });



            var result = await _readingQuestionCriterionTrialRepository.SaveChangesAsync();


            return ResponseOutput.Ok(result);
        }

        /// <summary>
        /// 获取签名文本
        /// </summary>
        /// <param name="signCode"></param>
        /// <returns></returns>
        [HttpGet("{signCode}")]
        public async Task<IResponseOutput> GetSignText(string signCode)
        {
            var signRawText = await _repository.Where<SystemBasicData>(t => t.Code == signCode).Select(t => new { t.Code, t.Value, t.ValueCN, t.Id, ParentValue = t.Parent.Value, ParentValueCN = t.Parent.ValueCN }).FirstOrDefaultAsync();

            if (signRawText == null)
            {
                return ResponseOutput.NotOk("该操作需要电子签名确认，但未在系统中找到该场景的签名模板。");
            }

            return ResponseOutput.Ok(new
            {
                SignCodeId = signRawText.Id,
                SignCode = signRawText.Code,
                SignText = _userInfo.IsEn_Us ? signRawText.ParentValue.Replace("xxx", signRawText.Value) : signRawText.ParentValueCN.Replace("xxx", signRawText.ValueCN),
                //SignTextCN = signRawText.ParentValueCN.Replace("xxx", signRawText.Value)
            });
        }


        //验证  仅仅在 Initializing/Ongoing  才可以操作
        private async Task VerifyOnlyInOngoingOrInitialIzingOptAsync(Guid trialId)
        {
            if (!await _trialRepository.AnyAsync(t => t.Id == trialId && (t.TrialStatusStr == StaticData.TrialState.TrialInitializing || t.TrialStatusStr == StaticData.TrialState.TrialOngoing)))
            {
                throw new BusinessValidationFailedException("该项目已结束或停止，不允许修改配置。");
            }
        }


        /// <summary>
        /// 验证签名确认
        /// </summary>
        /// <param name="signConfirmDTO"></param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        [HttpPost]
        public async Task<IResponseOutput> VerifyTrialConfigSignatureConfirm(SignConfirmDTO signConfirmDTO)
        {
            var trialConfig = (await _trialRepository
                  .Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification })
                  .FirstOrDefaultAsync(t => t.TrialId == signConfirmDTO.TrialId))
                  .IfNullThrowException();


            var showOrderList = await _repository.Where<TrialQCQuestion>(t => t.TrialId == signConfirmDTO.TrialId).Select(t =>
            new { t.ShowOrder, ParentShowOrder = (int?)t.ParentQCQuestion.ShowOrder }).ToListAsync();

            if (trialConfig.QCProcessEnum ==
                TrialQCProcess.DoubleAudit || trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
            {
                if (showOrderList.Count == 0)
                {
                    throw new BusinessValidationFailedException("当前未添加影像质控审核问题。请先添加影像质控审核问题，再进行确认。");
                }
            }

            if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count())
            {
                throw new BusinessValidationFailedException("影像质控审核问题显示序号不能重复。");
            }

            if (showOrderList.Where(t => t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder))
            {
                throw new BusinessValidationFailedException("父问题的显示序号要比子问题的显示序号小，请确认。");
            }

            if (await _trialRepository.AnyAsync(t => t.Id == signConfirmDTO.TrialId && t.QCQuestionConfirmedUserId != null && t.QCQuestionConfirmedUserId != _userInfo.Id))
            {
                throw new BusinessValidationFailedException("影像质控审核问题已被其他人员确认，不允许再次确认。");
            }

            return ResponseOutput.Ok();
        }



        /// <summary>
        /// 签名确认   包括项目的三组配置 +  QC问题确认     后修改状态  (适用于不会回退的，项目废除、状态修改， 存在回退 不在这里弄，提供单独接口修改状态)
        /// </summary>
        /// <returns></returns>
               //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task<IResponseOutput> TrialConfigSignatureConfirm(SignConfirmDTO signConfirmDTO)
        {
            await VerifyOnlyInOngoingOrInitialIzingOptAsync(signConfirmDTO.TrialId);



            if (signConfirmDTO.SignCode == ((int)SignEnum.TrialLogicConfim).ToString())
            {
                await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialBasicLogicConfirmed = true });
            }
            else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialProcessConfim).ToString())
            {
                await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialProcessConfirmed = true });
            }
            else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialUrgentConfim).ToString())
            {
                await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true });
            }
            else

            if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString())
            {

                var trialConfig = (await _trialRepository
                    .Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification })
                    .FirstOrDefaultAsync(t => t.TrialId == signConfirmDTO.TrialId))
                    .IfNullThrowException();


                var showOrderList = await _repository.Where<TrialQCQuestion>(t => t.TrialId == signConfirmDTO.TrialId).Select(t =>
                new { t.ShowOrder, ParentShowOrder = (int?)t.ParentQCQuestion.ShowOrder }).ToListAsync();

                if (trialConfig.QCProcessEnum ==
                    TrialQCProcess.DoubleAudit || trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
                {
                    if (showOrderList.Count == 0)
                    {
                        throw new BusinessValidationFailedException("当前未添加影像质控审核问题。请先添加影像质控审核问题，再进行确认。");
                    }
                }

                if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count())
                {
                    throw new BusinessValidationFailedException("影像质控审核问题显示序号不能重复。");
                }

                if (showOrderList.Where(t => t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder))
                {
                    throw new BusinessValidationFailedException("父问题的显示序号要比子问题的显示序号小，请确认。");
                }

                if (await _trialRepository.AnyAsync(t => t.Id == signConfirmDTO.TrialId && t.QCQuestionConfirmedUserId != null && t.QCQuestionConfirmedUserId != _userInfo.Id))
                {
                    throw new BusinessValidationFailedException("影像质控审核问题已被其他人员确认，不允许再次确认。");
                }

                await _trialQCQuestionRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion
                {
                    IsConfirm = true
                });
                await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.Id, IsQCQuestionConfirmed = true });
                await _trialRepository.SaveChangesAsync();
            }



            return ResponseOutput.Ok();
        }



        /// <summary>
        /// 配置 基础逻辑信息
        /// </summary>
        /// <param name="trialConfig"></param>
        /// <returns></returns>
        [HttpPut]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> ConfigTrialBasicInfo(BasicTrialConfig trialConfig)
        {
            await VerifyOnlyInOngoingOrInitialIzingOptAsync(trialConfig.TrialId);

            var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException();

            trialConfig.Modalitys = $"|{String.Join('|', trialConfig.ModalityList)}|";
            _mapper.Map(trialConfig, trialInfo);
            trialInfo.UpdateTime = DateTime.Now;




            return ResponseOutput.Ok(await _repository.SaveChangesAsync());
        }

        /// <summary>
        /// 配置流程
        /// </summary>
        /// <param name="trialConfig"></param>
        /// <returns></returns>
        [HttpPut]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> ConfigTrialProcessInfo(TrialProcessConfig trialConfig)
        {
            if (!await _trialRepository.Where(t => t.Id == trialConfig.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialState.TrialInitializing))
            {
                return ResponseOutput.NotOk("该项目当前状态不是初始化，不允许进行该操作。");
            }




            var trialInfo = await _trialRepository.Where(t => t.Id == trialConfig.TrialId, true).Include(t => t.TrialDicList.Where(u => u.KeyName == StaticData.Criterion)).FirstOrDefaultAsync();
            if (trialInfo == null) return Null404NotFound(trialInfo);


            _mapper.Map(trialConfig, trialInfo);

            //if (trialInfo.IsGlobalReading && (trialInfo.IsArbitrationReading ?? false))
            //{
            //    trialInfo.ArbitrationRule = ArbitrationRule.Reading;
            //}

            //if (!trialInfo.IsGlobalReading && (trialInfo.IsArbitrationReading ?? false))
            //{
            //    trialInfo.ArbitrationRule = ArbitrationRule.Visit;
            //}
            trialInfo.UpdateTime = DateTime.Now;

            // 修改临床数据
            var noconfirmids = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == trialConfig.TrialId && !trialConfig.ClinicalDataTrialSetIds.Contains(x.Id)).Select(x => x.Id).ToListAsync();
            foreach (var item in trialConfig.ClinicalDataTrialSetIds)
            {
                await _clinicalDataTrialSetRepository.UpdatePartialFromQueryAsync(item, x => new ClinicalDataTrialSet()
                {

                    IsConfirm = true
                });
            }

            foreach (var item in noconfirmids)
            {
                await _clinicalDataTrialSetRepository.UpdatePartialFromQueryAsync(item, x => new ClinicalDataTrialSet()
                {

                    IsConfirm = false
                });
            }

            // 修改阅片标准
            var cancelConfirmCriterionIds = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == trialConfig.TrialId && x.IsConfirm && !trialConfig.TrialCriterionIds.Contains(x.Id)).Select(x => x.Id).ToListAsync();

            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => cancelConfirmCriterionIds.Contains(x.Id), x => new ReadingQuestionCriterionTrial()
            {
                IsConfirm = false
            });

            await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => trialConfig.TrialCriterionIds.Contains(x.Id), x => new ReadingQuestionCriterionTrial()
            {
                IsConfirm = true
            }); ;




            return ResponseOutput.Ok(await _repository.SaveChangesAsync());
        }

        /// <summary>
        /// 配置加急信息
        /// </summary>
        /// <param name="trialConfig"></param>
        /// <returns></returns>
        [HttpPut]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> ConfigTrialUrgentInfo(TrialUrgentConfig trialConfig)
        {

            await VerifyOnlyInOngoingOrInitialIzingOptAsync(trialConfig.TrialId);


            var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException();


            //项目紧急  当前所有已提交，但未完成的检查批次，设置为加急。后续提交的检查批次也设置为加急 （在提交的时候，回去判断 项目加急，Subject加急，是否入组确认，是否Pd，从而设置检查批次是否加急）
            if (trialConfig.IsUrgent)
            {

                await _repository.BatchUpdateAsync<SubjectVisit>(t => t.TrialId == trialInfo.Id && t.SubmitState == SubmitStateEnum.Submitted && t.ForwardState < ForwardStateEnum.Forwarded,
                    s => new SubjectVisit() { IsUrgent = trialConfig.IsUrgent });
            }
            else //之前设置为加急的检查批次状态不变。后续提交的检查批次，为不加急。
            {

            }

            _mapper.Map(trialConfig, trialInfo);

            trialInfo.UpdateTime = DateTime.Now;

            return ResponseOutput.Ok(await _repository.SaveChangesAsync());
        }

        [HttpGet("{trialId:guid}")]
        public async Task<IResponseOutput> IfTrialCanOngoing(Guid trialId)
        {
            var canOPt = await _trialRepository.AnyAsync(trial =>
                trial.Id == trialId && trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed &&
                trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed);
            return ResponseOutput.Ok(canOPt, msg: canOPt ? "" : "该项目的项目配置（基础配置、流程配置、加急配置） 、检查批次管理，有配置未确认，不能设置项目状态为启动。");
        }

        /// <summary>
        /// 更新项目状态
        /// </summary>
        /// <param name="trialId"></param>
        /// <param name="trialStatusStr"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        [HttpPut("{trialId:guid}/{trialStatusStr}/{reason?}")]
        [UnitOfWork]
        //[Authorize(Policy = IRaCISPolicy.PM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> UpdateTrialState(Guid trialId, string trialStatusStr, string? reason)
        {

            var trial = (await _trialRepository.Where(t => t.Id == trialId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();

            if (trialStatusStr == StaticData.TrialState.TrialOngoing)
            {
                if (trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed && trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed)
                {

                }
                else
                {
                    return ResponseOutput.NotOk("无法变更项目状态。该项目的项目配置、检查批次管理中，有未确认项");
                }
            }

            if ((trialStatusStr == StaticData.TrialState.TrialStopped || trialStatusStr == StaticData.TrialState.TrialCompleted) && trial.TrialStatusStr != StaticData.TrialState.TrialOngoing)
            {
                return ResponseOutput.NotOk("项目没有进入启动状态，不能设置为停止或完成状态");
            }

            //if (trialStatusStr != StaticData.TrialState.TrialOngoing)
            //{
            //    trial.TrialFinishTime = DateTime.Now;
            //}

            trial.TrialStateChangeList.Add(new TrialStateChange() { OriginState = trial.TrialStatusStr, NowState = trialStatusStr, Reason = reason ?? String.Empty, TrialId = trialId });

            trial.TrialStatusStr = trialStatusStr;


            //Paused、 添加工总量  算医生读片中
            if (trialStatusStr.Contains(StaticData.TrialState.TrialCompleted))
            {
                await _repository.BatchUpdateAsync<Enroll>(u => u.TrialId == trialId, e => new Enroll
                {
                    EnrollStatus = EnrollStatus.Finished
                });

                await _trialRepository.BatchUpdateNoTrackingAsync(u => u.Id == trialId, s => new Trial { TrialFinishedTime = DateTime.Now });

            }

            await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7));

            await _repository.SaveChangesAsync();

            return ResponseOutput.Ok();
        }

        /// <summary>
        /// 项目状态 变更历史  
        /// </summary>
        /// <param name="trialId"></param>
        /// <returns></returns>

        [HttpGet("{trialId:guid}")]
        public async Task<List<TrialStateChangeDTO>> GetTrialStateChangeList(Guid trialId)
        {
            return await _repository.Where<TrialStateChange>(t => t.TrialId == trialId).ProjectTo<TrialStateChangeDTO>(_mapper.ConfigurationProvider).ToListAsync();
        }


        /// <summary>
        /// 废除项目
        /// </summary>
        /// <param name="trialId"></param>
        /// <param name="isAbandon"></param>
        /// <returns></returns>
        [HttpPut("{trialId:guid}/{isAbandon:bool}")]
        //[Authorize(Policy = IRaCISPolicy.PM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> AbandonTrial(Guid trialId, /*Guid? signId,*/ bool isAbandon)
        {

            await _trialRepository.UpdatePartialFromQueryAsync(trialId, u => new Trial()
            {
                IsDeleted = isAbandon,
                TrialFinishTime = isAbandon ? DateTime.Now : null
            }, true);


            return ResponseOutput.Ok();
        }



        /// <summary>
        /// 获取 配置的所有信息  没有分多个接口  
        /// </summary>
        /// <param name="trialId"></param>
        /// <returns></returns>
        [HttpGet("{trialId:guid}")]
        public async Task<TrialConfigDTO> GetTrialConfigInfo(Guid trialId)
        {
            return await _trialRepository.Where(t => t.Id == trialId).ProjectTo<TrialConfigDTO>(_mapper.ConfigurationProvider)
                .FirstOrDefaultAsync().IfNullThrowException();
        }


        /// <summary>
        /// 配置项目任务信息
        /// </summary>
        /// <param name="trialConfig"></param>
        /// <returns></returns>
        [HttpPut]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        //[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> ConfigTrialTaskInfo(TrialTaskConfig trialConfig)
        {
            var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException();

            _mapper.Map(trialConfig, trialInfo);

            return ResponseOutput.Ok(await _trialRepository.SaveChangesAsync());
        }


        /// <summary>
        /// 配置项目读片查看规则
        /// </summary>
        /// <param name="trialConfig"></param>
        /// <returns></returns>
        [HttpPut]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
        //[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> ConfigTrialReadingTaskViewRule(TrialReadingTaskViewConfig trialConfig)
        {
            var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException();

            _mapper.Map(trialConfig, trialInfo);

            return ResponseOutput.Ok(await _trialRepository.SaveChangesAsync());
        }



    }
}
