using AutoMapper;
using EasyCaching.Core;
using EntityFrameworkCore.Triggered;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;

namespace IRaCIS.Core.Application.Triggers
{
    /// <summary>
    ///  处理  访视   末次评估  会影响Subject 状态
    /// </summary>
    public class SubjectVisitCheckPassedTrigger : IAfterSaveTrigger<SubjectVisit>
    {
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<VisitTask> _visitTaskRepository;

        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<TaskAllocationRule> _taskAllocationRuleRepository;

        private readonly IEasyCachingProvider _provider;
        private readonly IVisitTaskHelpeService _visitTaskHelpeService;

        private readonly IMapper _mapper;

        public SubjectVisitCheckPassedTrigger(IRepository<SubjectVisit> subjectVisitRepository, IRepository<VisitTask> visitTaskRepository,
            IRepository<Trial> trialRepository,
            IRepository<TaskAllocationRule> taskAllocationRuleRepository,
            IEasyCachingProvider provider,
            IVisitTaskHelpeService visitTaskHelpeService,
            IMapper mapper)
        {
            _subjectVisitRepository = subjectVisitRepository;
            _visitTaskRepository = visitTaskRepository;
            _provider = provider;
            _mapper = mapper;
            _taskAllocationRuleRepository = taskAllocationRuleRepository;
            _trialRepository = trialRepository;
            _visitTaskHelpeService = visitTaskHelpeService;
        }

        public async Task AfterSave(ITriggerContext<SubjectVisit> context, CancellationToken cancellationToken)
        {

            var subjectVisit = context.Entity;


            if (context.ChangeType == ChangeType.Modified)
            {

                // 一致性核查通过  生成读片任务
                if (context.UnmodifiedEntity?.CheckState != subjectVisit.CheckState && subjectVisit.CheckState == CheckStateEnum.CVPassed)
                {

                    #region 产生任务并分配 暂时废弃

                    //if (_taskAllocationRuleRepository.Where(t => t.TrialId == subjectVisit.TrialId && t.IsEnable).Count() < 2)
                    //{
                    //    throw new BusinessValidationFailedException("能参与读片的医生数量必须大于2,自动分配任务中止");
                    //}

                    //var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == subjectVisit.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();

                    //var cacheMaxCodeInt = _provider.Get<int>($"{subjectVisit.TrialId }_{ StaticData.CacheKey.TaskMaxCode}").Value;

                    //int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;

                    //_provider.Set<int>($"{subjectVisit.TrialId }_{ StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt + 2, TimeSpan.FromMinutes(30));

                    //var trialConfig = (await _trialRepository.Where(t => t.Id == subjectVisit.TrialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.TaskAllocateDefaultState, t.TaskAllocateObjEnum }).FirstOrDefaultAsync()).IfNullThrowException();

                    ////统计当前医生分配信息  有效医生数量必须大于2 已做验证
                    //var allocateStat = _taskAllocationRuleRepository.Where(t => t.TrialId == subjectVisit.TrialId && t.IsEnable).ProjectTo<AllocateInfo>(_mapper.ConfigurationProvider).ToList();

                    //if (trialConfig.ReadingType == ReadingMethod.Double)
                    //{

                    //    //每个访视 根据项目配置生成任务  双审生成两个 
                    //    var task1 = await _visitTaskRepository.AddAsync(new VisitTask()
                    //    {
                    //        TrialId = subjectVisit.TrialId,
                    //        SubjectId = subjectVisit.SubjectId,
                    //        IsUrgent = subjectVisit.IsUrgent,
                    //        TaskBlindName = subjectVisit.BlindName,
                    //        TaskName = subjectVisit.VisitName,
                    //        CheckPassedTime = subjectVisit.CheckPassedTime,
                    //        ArmEnum = 1,//特殊
                    //        Code = currentMaxCodeInt + 1,
                    //        TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
                    //        ReadingCategory = ReadingCategory.Visit
                    //    });

                    //    var task2 = await _visitTaskRepository.AddAsync(new VisitTask()
                    //    {
                    //        TrialId = subjectVisit.TrialId,
                    //        SubjectId = subjectVisit.SubjectId,
                    //        IsUrgent = subjectVisit.IsUrgent,
                    //        TaskBlindName = subjectVisit.BlindName,
                    //        TaskName = subjectVisit.VisitName,
                    //        CheckPassedTime = subjectVisit.CheckPassedTime,
                    //        ArmEnum = 2,//特殊
                    //        Code = currentMaxCodeInt + 2,
                    //        TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 2, nameof(VisitTask)),
                    //        ReadingCategory = ReadingCategory.Visit
                    //    });


                    //    if (trialConfig.TaskAllocateDefaultState == TaskAllocateDefaultState.Allocated)
                    //    {
                    //        task1.TaskAllocationState = TaskAllocationState.Allocated;
                    //        task2.TaskAllocationState = TaskAllocationState.Allocated;
                    //    }
                    //    else if (trialConfig.TaskAllocateDefaultState == TaskAllocateDefaultState.InitAllocated)
                    //    {
                    //        task1.TaskAllocationState = TaskAllocationState.InitAllocated;
                    //        task2.TaskAllocationState = TaskAllocationState.InitAllocated;
                    //    }

                    //    if (trialConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject)
                    //    {

                    //        //该Subject 之前是否有已分配的   如果改变配置  可能会出现  一个Subject 分配的同一个医生 有的在Arm1 有的在Arm2
                    //        var allocateSubjectArmList = _visitTaskRepository.Where(t => t.SubjectId == subjectVisit.SubjectId && t.TrialId == subjectVisit.TrialId && t.DoctorUserId != null).Select(t => new { t.DoctorUserId, t.ArmEnum }).Distinct().ToList();

                    //        //初次自动分配
                    //        if (allocateSubjectArmList.Count == 0)
                    //        {
                    //            //排除已经入选其他Arm的阅片人

                    //            //是否有做过Arm1的医生  没有新的医生未分配
                    //            if (allocateStat.Any(t => t.ArmList.Any(t => t == 1)) && !allocateStat.Any(t => t.ArmList.Count == 0))
                    //            {

                    //                task1.DoctorUserId = allocateStat.Where(t => t.ArmList.Any(t => t == 1)).OrderByDescending(t => t.TotalTaskCount * t.PlanReadingRatio * 0.01 - t.SelfTaskCount).ThenByDescending(t => t.PlanReadingRatio).FirstOrDefault().DoctorUserId;

                    //            }
                    //            else
                    //            {
                    //                //找到最优的需要分配任务的医生
                    //                task1.DoctorUserId = allocateStat.OrderByDescending(t => t.TotalTaskCount * t.PlanReadingRatio * 0.01 - t.SelfTaskCount).ThenByDescending(t => t.PlanReadingRatio).FirstOrDefault().DoctorUserId;

                    //                //分配之后，加入进去
                    //                allocateStat.FirstOrDefault(t => t.DoctorUserId == task1.DoctorUserId).ArmList.Add(1);
                    //            }


                    //            //是否有做过Arm2的医生   有新的医生未分配 按照最优法找
                    //            if (allocateStat.Any(t => t.ArmList.Any(t => t == 2)) && !allocateStat.Any(t => t.ArmList.Count == 0))
                    //            {

                    //                task2.DoctorUserId = allocateStat.Where(t => t.ArmList.Any(t => t == 2)).OrderByDescending(t => t.TotalTaskCount * t.PlanReadingRatio * 0.01 - t.SelfTaskCount).ThenByDescending(t => t.PlanReadingRatio).FirstOrDefault().DoctorUserId;
                    //            }
                    //            else
                    //            {
                    //                //找到最优的需要分配任务的医生
                    //                task2.DoctorUserId = allocateStat.OrderByDescending(t => t.TotalTaskCount * t.PlanReadingRatio * 0.01 - t.SelfTaskCount).ThenByDescending(t => t.PlanReadingRatio).Skip(1).FirstOrDefault().DoctorUserId;
                    //            }

                    //        }
                    //        else
                    //        {
                    //            if (allocateSubjectArmList.GroupBy(t => t.DoctorUserId).Any(g => g.Count() == 2))
                    //            {
                    //                throw new BusinessValidationFailedException("请确认是否改了配置，导致同一受试者 分配给同一个医生 在不同的Arm,无法完成自动分配");
                    //            }

                    //            //手动分配的时候  如果只分配了Arm1  没有分配Arm2 就会有问题
                    //            if (!(allocateSubjectArmList.Any(t => t.ArmEnum == 1) && allocateSubjectArmList.Any(t => t.ArmEnum == 2)))
                    //            {
                    //                throw new BusinessValidationFailedException("请确认是否改了配置，或者手动分配时，只分配了一个Arm ");
                    //            }

                    //            //分配给对应Arm的人
                    //            task1.DoctorUserId = allocateSubjectArmList.FirstOrDefault(t => t.ArmEnum == 1).DoctorUserId;
                    //            task2.DoctorUserId = allocateSubjectArmList.FirstOrDefault(t => t.ArmEnum == 2).DoctorUserId;
                    //        }

                    //        task1.AllocateTime = DateTime.Now;
                    //        task2.AllocateTime = DateTime.Now;
                    //    }

                    //}
                    //else if (trialConfig.ReadingType == ReadingMethod.Single)
                    //{
                    //    var singleTask = await _visitTaskRepository.AddAsync(new VisitTask()
                    //    {
                    //        TrialId = subjectVisit.TrialId,
                    //        SubjectId = subjectVisit.SubjectId,
                    //        IsUrgent = subjectVisit.IsUrgent,
                    //        TaskBlindName = subjectVisit.BlindName,
                    //        TaskName = subjectVisit.VisitName,
                    //        CheckPassedTime = subjectVisit.CheckPassedTime,
                    //        ArmEnum = 0, //特殊
                    //        Code = currentMaxCodeInt + 1,
                    //        TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
                    //        ReadingCategory = ReadingCategory.Visit
                    //    });

                    //    if (trialConfig.TaskAllocateDefaultState == TaskAllocateDefaultState.Allocated)
                    //    {
                    //        singleTask.TaskAllocationState = TaskAllocationState.Allocated;
                    //    }
                    //    else if (trialConfig.TaskAllocateDefaultState == TaskAllocateDefaultState.InitAllocated)
                    //    {
                    //        singleTask.TaskAllocationState = TaskAllocationState.InitAllocated;
                    //    }

                    //    if (trialConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject)
                    //    {
                    //        //该Subject 之前是否有已分配的   如果改变配置  可能会出现  一个Subject 分配的同一个医生 有的在Arm1 有的在Arm2
                    //        var allocateSubjectArmList = _visitTaskRepository.Where(t => t.SubjectId == subjectVisit.SubjectId && t.TrialId == subjectVisit.TrialId && t.DoctorUserId != null).Select(t => new { t.DoctorUserId, t.ArmEnum }).Distinct().ToList();

                    //        //初次自动分配
                    //        if (allocateSubjectArmList.Count == 0)
                    //        {
                    //            singleTask.DoctorUserId = allocateStat.OrderByDescending(t => t.TotalTaskCount * t.PlanReadingRatio * 0.01 - t.SelfTaskCount).ThenByDescending(t => t.PlanReadingRatio).FirstOrDefault().DoctorUserId;
                    //        }
                    //        else
                    //        {
                    //            singleTask.DoctorUserId = allocateSubjectArmList.FirstOrDefault(t => t.ArmEnum == 0).DoctorUserId;
                    //        }


                    //    }

                    //}


                    //await _visitTaskRepository.SaveChangesAsync();

                    #endregion

                    await _visitTaskHelpeService.GenerateVisitTaskAsync(subjectVisit.TrialId, new List<Guid>() { subjectVisit.Id }, true);
                }

            }

        }





    }
}