using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Application.Filter;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Service.WorkLoad.DTO;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Share.Reading;
using MassTransit;
using IRaCIS.Core.Infra.EFCore.Common;

namespace IRaCIS.Application.Services
{
    /// <summary>
    /// 阅片期配置
    /// </summary>
    [ApiExplorerSettings(GroupName = "Reading")]
    public class ReadingPeriodSetService : BaseService
    {

        public IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<ReadingPeriodSet> _readingPeriodSetRepository;
        private readonly IRepository<ReadModule> _readModuleRepository;
        private readonly IRepository<Site> _siteSetRepository;

        public ReadingPeriodSetService(IRepository<SubjectVisit> subjectVisitRepository,
            IRepository<ReadingPeriodSet> ReadingPeriodSetRepository,
             IRepository<ReadModule> readModuleRepository,
           IRepository<Site> SiteSetRepository
          )
        {
            _subjectVisitRepository = subjectVisitRepository;
            _readingPeriodSetRepository = ReadingPeriodSetRepository;
            this._readModuleRepository = readModuleRepository;
            _siteSetRepository = SiteSetRepository;
        }


        /// <summary>
        /// 新增或者修改
        /// </summary>
        /// <param name="addOrEditReadingPeriodSet"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> AddOrUpdateReadingPeriodSet(ReadingPeriodSetAddOrEdit addOrEditReadingPeriodSet)
        {
            if (addOrEditReadingPeriodSet.Id == null)
            {
                var entity = _mapper.Map<ReadingPeriodSet>(addOrEditReadingPeriodSet);
                entity.ReadingPeriodSites = addOrEditReadingPeriodSet.SiteIds.Select(x => new ReadingPeriodSite()
                {
                    ReadingPeriodSetId = entity.Id,
                    TrialId =entity.TrialId,
                    SiteId = x,
                }).ToList();

                await _readingPeriodSetRepository.AddAsync(entity, true);
                return ResponseOutput.Ok();
            }
            else
            {
                var entity = (await _readingPeriodSetRepository.Where(t => t.Id == addOrEditReadingPeriodSet.Id, true).Include(t => t.ReadingPeriodSites).FirstOrDefaultAsync()).IfNullThrowException();
                _mapper.Map(addOrEditReadingPeriodSet, entity);
                entity.ReadingPeriodSites = addOrEditReadingPeriodSet.SiteIds.Select(x => new ReadingPeriodSite()
                {
                    ReadingPeriodSetId = entity.Id,
                    TrialId = entity.TrialId,
                    SiteId = x,
                }).ToList();
                var success = await _readingPeriodSetRepository.SaveChangesAsync();
                return ResponseOutput.Ok();

            }
        }

        /// <summary>
        /// 获取影像阅片的预览
        /// </summary>
        /// <returns></returns>
        public async Task<List<PreviewTheReadingListOutDto>> GetPreviewTheReadingList(PreviewTheReadingListInDto inDto)
        {
            var readset = (await _readingPeriodSetRepository.Where(x => x.Id == inDto.ReadingPeriodSetId).Include(x => x.ReadingPeriodSites).FirstOrDefaultAsync()).IfNullThrowConvertException();
            var visitquery = _subjectVisitRepository.Where(x => x.TrialId == readset.TrialId && x.LatestScanDate != null && x.InPlan);
            if (readset.ReadingScope == ReadingScopeEnum.Site)
            {
                var siteids = readset.ReadingPeriodSites.Select(x => x.Id);
                visitquery = visitquery.Where(x => siteids.Contains(x.SiteId));
            }

            visitquery = visitquery.WhereIf(readset.ExpirationDate != null, x => x.LatestScanDate <= readset.ExpirationDate.Value)
                .WhereIf(readset.ExpirationVisitNum != null, x => x.VisitNum <= readset.ExpirationVisitNum);
            var visits = (await visitquery.Include(x=>x.Subject).Include(x=>x.TrialSite).GroupBy(x => x.SubjectId).Select(x => new
            {
                SubjectId = x.Key,
                visit = x.OrderByDescending(x => x.VisitNum).FirstOrDefault()
            }).ToListAsync()).Select(x => x.visit).ToList();


           return   visits.Where(x => _readModuleRepository.Where(y => y.ReadingSetType == readset.ReadingSetType && x.Id == y.SubjectVisitId).Count() == 0)
                .Select(x => new PreviewTheReadingListOutDto
                { 
                     ExpirationDate= readset.ExpirationDate,
                     SubjectVisitId= x.Id,
                     TrialSiteCode = x.TrialSite.TrialSiteCode,
                     LatestScanDate=x.LatestScanDate,
                     ReadingPeriodName= readset.ReadingPeriodName,
                     ReadingPeriodSetId=readset.Id,
                     SubjectCode=x.Subject.Code,
                     SubjectId=x.SubjectId,
                     Remark= readset.Remark
                }).ToList();
        }

        /// <summary>
        /// 添加对应的阅片
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<IResponseOutput> ReadingToGenerate(ReadingToGenerateInDto inDto)
        {
            var readset = (await _readingPeriodSetRepository.Where(x => x.Id == inDto.ReadingPeriodSetId).Include(x => x.ReadingPeriodSites).FirstOrDefaultAsync()).IfNullThrowConvertException();
            var visits = await _subjectVisitRepository.Where(x => inDto.SubjectVisitIds.Contains(x.Id)).ToListAsync();

            List<ReadModule> readModules = new List<ReadModule>();

            foreach (var item in visits)
            {
                readModules.Add(new ReadModule()
                {
                    Id = NewId.NextGuid(),
                    SubjectId = item.SubjectId,
                    ModuleType = readset.ReadingSetType == ReadingSetType.ImageReading ? ModuleTypeEnum.Read : ModuleTypeEnum.Oncology,
                    IsUrgent = item.IsUrgent,
                    ModuleName = readset.ReadingPeriodName,
                    SubjectVisitId = item.Id,
                    ReadingSetType = readset.ReadingSetType,
                    Status = ReadingCommon.GetVisitSubmitStateEnum(item),
                });
            };

            await _readModuleRepository.AddRangeAsync(readModules);


            var res = await _subjectVisitRepository.SaveChangesAsync();


            return ResponseOutput.Result(res);
        }

        /// <summary>
        /// 分页获取
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<ReadingPeriodSetView>>  GetReadingPeriodSetList(ReadingPeriodSetQuery query)
		{
		     var readquery =_readingPeriodSetRepository.AsQueryable().Include(x=>x.ReadingPeriodSites)
                .WhereIf(query.TrialId!=null,x=>x.TrialId==query.TrialId)
                .WhereIf(query.ReadingPeriodName != null, x => x.ReadingPeriodName.Contains(query.ReadingPeriodName))
                .ProjectTo<ReadingPeriodSetView>(_mapper.ConfigurationProvider);
                var pageList= await readquery.ToPagedListAsync(query.PageIndex, query.PageSize, query.SortField == null ? "CreateTime" : query.SortField,
               query.SortAsc);

            return pageList;
		}

        /// <summary>
        /// 获取单条
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost("{id:guid}")]
        public async Task<ReadingPeriodSetView> GetReadingPeriodSet(Guid id)
        {
            var data = await _readingPeriodSetRepository.AsQueryable().Include(x => x.ReadingPeriodSites).Where(x => x.Id == id).ProjectTo<ReadingPeriodSetView>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();

            return data;

        }


        /// <summary>
        /// 设置阅片期配置是否生效
        /// </summary>
        /// <param name="indto"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task<IResponseOutput> SetReadingPeriodSetEffect(SetReadingPeriodSetEffect indto)
        {
            var readquery =await _readingPeriodSetRepository.UpdatePartialNowNoQueryAsync(indto.Id, x => new ReadingPeriodSet() {
                IsTakeEffect = indto.IsTakeEffect
            });
         
            return ResponseOutput.Result(true);
        }



        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="readingPeriodSetId"></param>
        /// <returns></returns>
        [HttpDelete("{readingPeriodSetId:guid}")]
        public async Task<IResponseOutput> DeleteReadingPeriodSet(Guid readingPeriodSetId)
        {
            var success = await _repository.BatchDeleteAsync<ReadingPeriodSet>(t => t.Id == readingPeriodSetId);
            return ResponseOutput.Result(success);
        }
    }
}