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

using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Domain.Share;
using System.Linq.Expressions;
using IRaCIS.Core.Infra.EFCore.Common;

namespace IRaCIS.Core.Application.Service
{
    /// <summary>
    /// 一致性分析配置表
    /// </summary>	
    [ApiExplorerSettings(GroupName = "Trial")]
    public class TaskConsistentRuleService : BaseService, ITaskConsistentRuleService
    {

        private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
        private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<SubjectUser> _subjectUserRepository;
        private readonly IRepository<Subject> _subjectRepository;

        public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository)
        {
            _taskConsistentRuleRepository = taskConsistentRuleRepository;
            _visitTaskRepository = visitTaskRepository;
            _subjectUserRepository = subjectUserRepository;
            _subjectRepository = subjectRepository;
        }


        /// <summary>
        /// 一致性分析列表  (自身 组内  最后勾选 产生的任务)
        /// </summary>
        /// <param name="queryVisitTask"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<AnalysisTaskView>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask)
        {
            var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId)
                .Where(t => t.IsAnalysisCreate)

               .WhereIf(queryVisitTask.SiteId != null, t => t.Subject.SiteId == queryVisitTask.SiteId)
               .WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId)
               .WhereIf(queryVisitTask.IsUrgent != null, t => t.IsUrgent == queryVisitTask.IsUrgent)
               .WhereIf(queryVisitTask.DoctorUserId != null, t => t.DoctorUserId == queryVisitTask.DoctorUserId)
               .WhereIf(queryVisitTask.ReadingCategory != null, t => t.ReadingCategory == queryVisitTask.ReadingCategory)
               .WhereIf(queryVisitTask.ReadingTaskState != null, t => t.ReadingTaskState == queryVisitTask.ReadingTaskState)
               .WhereIf(queryVisitTask.TaskAllocationState != null, t => t.TaskAllocationState == queryVisitTask.TaskAllocationState)
               .WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName))
               .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => t.Subject.Code.Contains(queryVisitTask.SubjectCode))
               .WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
               .WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate.Value.AddDays(1))
               .ProjectTo<AnalysisTaskView>(_mapper.ConfigurationProvider);

            var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId) };

            var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);

            return (pageList);
        }


        /// <summary>
        /// 为自身一致性分析医生,选择Subejct 列表
        /// </summary>
        /// <param name="inQuery"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<DoctorConsistentRuleSubjectView>> GetDoctorSelfConsistentRuleSubjectList(ConsistentQuery inQuery)
        {
            var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inQuery.TaskConsistentRuleId);

            var (group, query) = GetIQueryableDoctorSelfConsistentRuleSubjectView(filterObj);

            var count = group.Count();

            query = query.OrderByDescending(t => t.IsHaveGeneratedTask).Skip((inQuery.PageIndex - 1) * inQuery.PageSize);

            var items = await query.Take(inQuery.PageSize).ToArrayAsync().ConfigureAwait(false);

            var pagedList = new PageOutput<DoctorConsistentRuleSubjectView>()
            {
                PageIndex = inQuery.PageIndex,
                PageSize = inQuery.PageSize,
                TotalCount = count,
                CurrentPageData = items
            };


            return pagedList;
        }

        /// <summary>
        /// 确认生成自身一致性分析任务
        /// </summary>
        /// <param name="inCommand"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> ConfirmGenerateSelfConsistentTask(ConsistentConfirmGenerateCommand inCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
        {
            var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inCommand.TaskConsistentRuleId);


            var (group, query) = GetIQueryableDoctorSelfConsistentRuleSubjectView(filterObj, inCommand.SubejctIdList);

            var list = query.OrderByDescending(t => t.IsHaveGeneratedTask).ToList();

            foreach (var subject in list)
            {
                subject.VisitTaskList.Take(filterObj.PlanVisitCount).ForEach(t => { t.DoctorUserId = filterObj.AnalysisDoctorUserId; t.TaskConsistentRuleId = filterObj.Id; });


                await _visitTaskCommonService.AddTaskAsync(new GenerateTaskCommand()
                {
                    TrialId = filterObj.TrialId,

                    ReadingCategory = ReadingCategory.SelfConsistent,

                    //产生的过滤掉已经生成的
                    GenerataConsistentTaskList = subject.VisitTaskList.Where(t => t.IsHaveGeneratedTask == false).ToList()
                });

            }


            return ResponseOutput.Ok();


        }




        private (IQueryable<IGrouping<Guid, VisitTask>>, IQueryable<DoctorConsistentRuleSubjectView>) GetIQueryableDoctorSelfConsistentRuleSubjectView(TaskConsistentRule filterObj, List<Guid>? subejctIdList = null)
        {


            //IQueryable<Guid> subjectfilter = default;

            //if (isSelfAnalysis == false)
            //{
            //    //过滤不满足的Subject  

            //    subjectfilter = _subjectUserRepository.Where(t => t.TrialId == filterObj.TrialId).GroupBy(t => t.SubjectId)
            //        .Where(g => g.Any(t => t.DoctorUserId == filterObj.AnalysisDoctorUserId) && !g.Any(t => t.DoctorUserId == filterObj.CompareDoctorUserId)).Select(g => g.Key);
            //}

            var doctorUserId = filterObj.AnalysisDoctorUserId;



            var group = _visitTaskRepository.Where(t => t.TrialId == filterObj.TrialId && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.DoctorUserId == doctorUserId)


                                        //  自身一致性分析
                                        //.WhereIf(isSelfAnalysis, t => t.DoctorUserId == filterObj.AnalysisDoctorUserId)
                                        //// 组内一致性分析
                                        //.WhereIf(isSelfAnalysis == false && subjectfilter != null, t => t.DoctorUserId == filterObj.AnalysisDoctorUserId && subjectfilter.Contains(t.SubjectId))
                                        //.WhereIf(subejctIdList != null && subejctIdList?.Count > 0, t => subejctIdList.Contains(t.SubjectId))
                                        .Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect)
                                        .Where(t => t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now)
                                        //重阅产生的访视任务  要把之前的访视任务去除
                                        .Where(t => t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)

                                        .WhereIf(filterObj.IsHaveReadingPeriod == true, t => t.SameSubjectVisiTaskList.Any(u => u.VisitTaskNum == t.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]
                                        && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now))
                                        .GroupBy(t => t.SubjectId)
                                        .Where(g => g.Count() >= filterObj.PlanVisitCount);


            var query = group.Select(g => new DoctorConsistentRuleSubjectView()
            {
                SubjectId = g.Key,

                IsHaveGeneratedTask = g.Any(c => c.SameSubjectVisiTaskList.Any(t => t.IsAnalysisCreate && t.DoctorUserId == doctorUserId && t.TaskConsistentRuleId == filterObj.Id)),

                VisitTaskList = g.OrderBy(t => t.VisitTaskNum)

               .Select(c => new VisitTaskSimpleView()
               {
                   Id = c.Id,
                   ReadingCategory = c.ReadingCategory,
                   ReadingTaskState = c.ReadingTaskState,
                   TaskBlindName = c.TaskBlindName,
                   TaskCode = c.TaskCode,
                   TaskName = c.TaskName,
                   TaskState = c.TaskState,
                   ArmEnum = c.ArmEnum,
                   SubjectId = c.SubjectId,
                   TrialId = c.TrialId,
                   SiteId = c.Subject.SiteId,
                   SubjectCode = c.Subject.Code,
                   TrialSiteCode = c.Subject.TrialSite.TrialSiteCode,

                   GlobalVisitTaskList = c.SameSubjectVisiTaskList.Where(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned).Select(t => new VisitTaskSimpleView()
                   {
                       Id = t.Id,
                       ReadingCategory = t.ReadingCategory,
                       ReadingTaskState = t.ReadingTaskState,
                       TaskBlindName = t.TaskBlindName,
                       TaskCode = t.TaskCode,
                       TaskName = t.TaskName,
                       TaskState = t.TaskState,
                       ArmEnum = t.ArmEnum,
                       SubjectId = t.SubjectId,
                       TrialId = t.TrialId,
                       SiteId = t.Subject.SiteId,
                       SubjectCode = t.Subject.Code,
                       TrialSiteCode = t.Subject.TrialSite.TrialSiteCode,
                   }).ToList(),

                   //RelationDoctorUserList = c.SourceSubjectVisit.VisitTaskList/*Where(t=>t.ReadingTaskState == ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect)*/.Select(c => new UserSimpleInfo()
                   //{
                   //    FullName = c.DoctorUser.FullName,
                   //    UserCode = c.DoctorUser.UserCode,
                   //    UserId = c.DoctorUser.Id,
                   //    UserName = c.DoctorUser.UserName
                   //}).ToList(),

                   IsHaveGeneratedTask = c.SameSubjectVisiTaskList.Any(t => t.ConsistentAnalysisOriginalTaskId == c.Id),

               }).ToList(),

                ValidTaskCount = g.Count()

            }); ;

            return (group, query);
        }

        /// <summary>
        /// 自身一致性分配 配置+  统计已经生成数量统计表
        /// </summary>
        /// <param name="inQuery"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<TaskConsistentRuleView>> GetSelfConsistentRuleList(TaskConsistentRuleQuery inQuery)
        {

            #region 是否有新的医生加入 自动加入配置


            if  (await _taskConsistentRuleRepository.AnyAsync(t => t.TrialId == inQuery.TrialId))
            {
                var rule = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId).ProjectTo<TaskConsistentRuleBatchAddOrEdit>(_mapper.ConfigurationProvider).FirstAsync();

                rule.IsBatchAdd = true;

                await BatchAddOrUpdateTaskConsistentRule(rule);
            }

            #endregion

            var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId)
             .ProjectTo<TaskConsistentRuleView>(_mapper.ConfigurationProvider);

            return await taskConsistentRuleQueryable.ToListAsync();
        }

        public async Task<IResponseOutput> BatchAddOrUpdateTaskConsistentRule(TaskConsistentRuleBatchAddOrEdit addOrEdit)
        {
            var trialId = addOrEdit.TrialId;



            if (addOrEdit.IsBatchAdd)
            {
                var query = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId)
                            join user in _repository.Where<User>() on enroll.DoctorId equals user.DoctorId
                            join taskConsistentRule in _repository.Where<TaskConsistentRule>(t=>t.TrialId== trialId) on user.Id equals taskConsistentRule.AnalysisDoctorUserId into c
                            from taskConsistentRule in c.DefaultIfEmpty()
                            select new
                            {
                                TrialId = enroll.TrialId,

                                DoctorUserId = user.Id,
                                //FullName = user.FullName,
                                //UserCode = user.UserCode,
                                //UserName = user.UserName,

                                IsHaveConfig = taskConsistentRule != null
                            };

                var doctorList = await query.ToListAsync();


                foreach (var doctor in doctorList)
                {
                    if (!doctor.IsHaveConfig)
                    {
                        var verifyExp1 = new EntityVerifyExp<TaskConsistentRule>()
                        {
                            VerifyExp = t => t.AnalysisDoctorUserId == doctor.DoctorUserId && t.TrialId == trialId,
                            VerifyMsg = "已有该医生配置,不允许继续增加"
                        };

                        addOrEdit.AnalysisDoctorUserId = doctor.DoctorUserId;
                        addOrEdit.Id = Guid.Empty ;

                        var entity = await _taskConsistentRuleRepository.InsertOrUpdateAsync(addOrEdit, true, verifyExp1);
                    }
                }
            }
            else
            {
                await _taskConsistentRuleRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId, c => new TaskConsistentRule()
                {
                    PlanSubjectCount = c.PlanSubjectCount,
                    PlanVisitCount = c.PlanVisitCount,
                    IntervalWeeks = c.IntervalWeeks,
                    IsGenerateGlobalTask = c.IsGenerateGlobalTask,
                    IsHaveReadingPeriod = c.IsHaveReadingPeriod

                }, true);
            }

            await _taskConsistentRuleRepository.SaveChangesAsync();

            return ResponseOutput.Ok();
        }



        public async Task<IResponseOutput> AddOrUpdateTaskConsistentRule(TaskConsistentRuleAddOrEdit addOrEditTaskConsistentRule)
        {

            var verifyExp1 = new EntityVerifyExp<TaskConsistentRule>()
            {
                VerifyExp = t => t.AnalysisDoctorUserId == addOrEditTaskConsistentRule.AnalysisDoctorUserId && t.TrialId == addOrEditTaskConsistentRule.TrialId,
                VerifyMsg = "已有该医生配置,不允许继续增加"
            };

            var entity = await _taskConsistentRuleRepository.InsertOrUpdateAsync(addOrEditTaskConsistentRule, true, verifyExp1);

            return ResponseOutput.Ok(entity.Id.ToString());

        }


        [HttpDelete("{taskConsistentRuleId:guid}")]
        public async Task<IResponseOutput> DeleteTaskConsistentRule(Guid taskConsistentRuleId)
        {
            var config = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == taskConsistentRuleId);


            if (await _visitTaskRepository.AnyAsync(t => t.IsAnalysisCreate && t.DoctorUserId == config.AnalysisDoctorUserId && t.TrialId == config.TrialId))
            {
                throw new BusinessValidationFailedException("已产生一致性分析任务,不允许删除");
            }



            var success = await _taskConsistentRuleRepository.DeleteFromQueryAsync(t => t.Id == taskConsistentRuleId, true);
            return ResponseOutput.Ok();
        }





    }
}