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

using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using EasyCaching.Core;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;

namespace IRaCIS.Core.Application.Service
{
    /// <summary>
    /// 访视读片任务
    /// </summary>	
    [ApiExplorerSettings(GroupName = "Trial")]
    public class VisitTaskHelpeService : IVisitTaskHelpeService
    {

        private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<Trial> _trialRepository;
        private readonly IEasyCachingProvider _provider;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<TaskAllocationRule> _taskAllocationRuleRepository;
        private readonly IRepository<SubjectUser> _subjectUserRepository;


        public VisitTaskHelpeService(IRepository<VisitTask> visitTaskRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Trial> trialRepository, IEasyCachingProvider provider, IRepository<SubjectVisit> subjectVisitRepository, IRepository<TaskAllocationRule> taskAllocationRuleRepository)
        {
            _visitTaskRepository = visitTaskRepository;
            _trialRepository = trialRepository;
            _provider = provider;
            _subjectVisitRepository = subjectVisitRepository;
            _taskAllocationRuleRepository = taskAllocationRuleRepository;
            _subjectUserRepository = subjectUserRepository;
        }

        //查询列表的时候,一致性核查通过未产生任务的 自动产生任务
        public async Task GenerateVisitTaskAsync(Guid trialId, List<Guid> subjectVisitIdList, bool isAssignSubjectToDoctor = false)
        {

            if (subjectVisitIdList.Count == 0)
            {
                return;
            }

            //以前访视未产生任务的,在查询这里要产生  后期维护到一块 

            var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.IsFollowVisitAutoAssign, t.IsFollowGlobalVisitAutoAssign, t.FollowGlobalVisitAutoAssignDefaultState, t.FollowVisitAutoAssignDefaultState, t.TaskAllocateObjEnum }).FirstOrDefaultAsync()).IfNullThrowException();

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

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

            int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;

            var subjectVisitList = _subjectVisitRepository.Where(t => subjectVisitIdList.Contains(t.Id)).Select(t => new { t.Id, t.SubjectId, t.IsUrgent, t.BlindName, t.VisitName, t.CheckPassedTime, t.TrialId }).Distinct().ToList();


            foreach (var subjectVisit in subjectVisitList)
            {

                var assignConfigList = await _subjectUserRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId).Select(u => new { u.DoctorUserId, u.ArmEnum }).ToListAsync();


                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 = Arm.DoubleReadingArm1,//特殊
                        Code = currentMaxCodeInt + 1,
                        SourceSubjectVisitId=subjectVisit.Id,
                        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 = Arm.DoubleReadingArm2,//特殊
                        Code = currentMaxCodeInt + 2,
                        SourceSubjectVisitId = subjectVisit.Id,
                        TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 2, nameof(VisitTask)),
                        ReadingCategory = ReadingCategory.Visit
                    });

                    currentMaxCodeInt = currentMaxCodeInt + 2;

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


                    #region 分配
                    if (isAssignSubjectToDoctor)
                    {



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

                            if (trialConfig.IsFollowVisitAutoAssign)
                            {

                                #region 验证历史任务

                                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();


                                //不是初次分配  直接分配给Subject 之前的医生
                                if (allocateSubjectArmList.Count != 0)
                                {
                                    if (_taskAllocationRuleRepository.Where(t => t.TrialId == subjectVisit.TrialId && t.IsEnable).Count() < 2)
                                    {
                                        throw new BusinessValidationFailedException("能参与读片的医生数量必须大于2,自动分配任务中止");
                                    }

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

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

                                    //配置了医生 
                                    if (assignConfigList.Count > 0)
                                    {
                                        var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskState.InitAllocated : TaskState.Allocated;


                                        task1.TaskState = defaultState;
                                        task2.TaskState = defaultState;

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

                                }
                                #endregion

                              
                            
                            }

                            //找到配置规则表 进行分配


                            else
                            {
                                //后续Subect  不自动分配  不处理
                                return;
                            }
                            //else if (trialConfig.IsFollowGlobalVisitAutoAssign)
                            //{
                            //    var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskState.InitAllocated : TaskState.Allocated;

                            //    task1.TaskState = defaultState;
                            //    task2.TaskState = defaultState;
                            //}




                        }


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


                    #endregion



                }
                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 = Arm.DoubleReadingArm1, //特殊
                        Code = currentMaxCodeInt + 1,
                        SourceSubjectVisitId = subjectVisit.Id,
                        TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
                        ReadingCategory = ReadingCategory.Visit
                    });

                    singleTask.AllocateTime = DateTime.Now;

                    currentMaxCodeInt = currentMaxCodeInt + 1;

                    _provider.Set<int>($"{trialId }_{ StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt + 1, TimeSpan.FromMinutes(30));

                    #region 分配
                    if (isAssignSubjectToDoctor)
                    {


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

                            if (trialConfig.IsFollowVisitAutoAssign)
                            {
                                

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

                                    //配置了医生 
                                    if (assignConfigList.Count > 0)
                                    {
                                        var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskState.InitAllocated : TaskState.Allocated;

                                        singleTask.TaskState = defaultState;

                                        singleTask.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == 0).DoctorUserId;
                                    }
                                }

                              
                            }
                            else
                            {
                                //后续Subect  不自动分配  不处理
                                return;
                            }
                        }



                    }
                    #endregion



                }


                await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.Id == subjectVisit.Id, u => new SubjectVisit() { IsVisitTaskGenerated = true });
                await _visitTaskRepository.SaveChangesAsync();
            }



        }






    }
}