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 MassTransit;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using Panda.DynamicWebApi.Attributes;

namespace IRaCIS.Application.Services
{
    /// <summary>
    /// 阅片临床数据
    /// </summary>
    [ApiExplorerSettings(GroupName = "Reading")]
    public class ReadingClinicalDataService : BaseService, IReadingClinicalDataService
    {
        private readonly IRepository<ReadingClinicalData> _readingClinicalDataRepository;
        private readonly IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository;
 
        private readonly IRepository<PreviousPDF> _previousPDFRepository;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IRepository<ReadingClinicalDataPDF> _readingClinicalDataPDFRepository;

        public ReadingClinicalDataService(IRepository<ReadingClinicalData> readingClinicalDataRepository,
            IRepository<ClinicalDataTrialSet> clinicalDataTrialSetRepository,
             IRepository<PreviousPDF> previousPDFRepository,
                IRepository<SubjectVisit> subjectVisitRepository,
              IRepository<ReadingClinicalDataPDF> readingClinicalDataPDFRepository
          )
        {
            this._readingClinicalDataRepository = readingClinicalDataRepository;
            this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository;
            this._previousPDFRepository = previousPDFRepository;
            this._subjectVisitRepository = subjectVisitRepository;
            this._readingClinicalDataPDFRepository = readingClinicalDataPDFRepository;
        }


        /// <summary>
        /// 新增或者修改
        /// </summary>
        /// <param name="indto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IResponseOutput> AddOrUpdateReadingClinicalData(AddOrUpdateReadingClinicalDataDto indto)
        {
            var existsQuery = _readingClinicalDataRepository
                .WhereIf(indto.Id != null,x=>x.Id!=indto.Id)
                .Where(x => x.ClinicalDataTrialSetId == indto.ClinicalDataTrialSetId&&x.ReadingId==indto.ReadingId);

            if (await existsQuery.AnyAsync())
            {
               return  ResponseOutput.NotOk("存在同类型的临床数据");
            }

            var clinicalDataTrialSet = (await _clinicalDataTrialSetRepository.Where(x => x.Id == indto.ClinicalDataTrialSetId).FirstOrDefaultAsync()).IfNullThrowException();
            if (indto.Id == null)
            {
                var entity = _mapper.Map<ReadingClinicalData>(indto);
                entity.ReadingClinicalDataPDFList = indto.AddFileList.Select(x => new ReadingClinicalDataPDF()
                {
                    TrialId = entity.TrialId,
                    SubjectId= indto.SubjectId,
                    FileName=x.FileName,
                    Path=x.Path,
                    ClinicalDataTrialSetId=indto.ClinicalDataTrialSetId,
                    IsVisit= indto.IsVisit,
                    ClinicalDataLevel= clinicalDataTrialSet.ClinicalDataLevel,
                    ReadingId=indto.ReadingId
                }).ToList();

            
                await _readingClinicalDataRepository.AddAsync(entity, true);
                var success = await _readingClinicalDataRepository.SaveChangesAsync();
                return ResponseOutput.Ok(entity.Id);
            }
            else
            {
                var entity = (await _readingClinicalDataRepository.Where(t => t.Id == indto.Id, true).FirstOrDefaultAsync()).IfNullThrowException();
                _mapper.Map(indto, entity);
                await _readingClinicalDataPDFRepository.DeleteFromQueryAsync(x => indto.DeleteFileIds.Contains(x.Id));
                await _readingClinicalDataRepository.SaveChangesAsync();
                var addFileList = indto.AddFileList.Select(x => new ReadingClinicalDataPDF()
                {

                    TrialId = entity.TrialId,
                    SubjectId = indto.SubjectId,
                    FileName = x.FileName,
                    Path = x.Path,
                    ClinicalDataTrialSetId = indto.ClinicalDataTrialSetId,
                    IsVisit = indto.IsVisit,
                    ClinicalDataLevel = clinicalDataTrialSet.ClinicalDataLevel,
                    ReadingId = indto.ReadingId,
                    ReadingClinicalDataId= entity.Id,
                }).ToList();
                await _readingClinicalDataPDFRepository.AddRangeAsync(addFileList);

                var success = await _readingClinicalDataRepository.SaveChangesAsync();
                return ResponseOutput.Ok(entity.Id);

            }
          
        }

        ///// <summary>
        ///// 设置临床数据是否盲化
        ///// </summary>
        ///// <returns></returns>
        //[HttpPost]
        //public async Task<IResponseOutput> SetReadingClinicalDataIsBlind(SetReadingClinicalDataIsBlind inDto)
        //{
        //    await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(inDto.Id, x=>new ReadingClinicalData() { 
        //         IsBlind=inDto.IsBlind,
        //    });
        //    return ResponseOutput.Ok(await _readingClinicalDataRepository.SaveChangesAsync());
        //}

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id:guid}")]
        public async Task<IResponseOutput> DeleteReadingClinicalData(Guid id)
        {
         
            await _readingClinicalDataRepository.DeleteFromQueryAsync(x => x.Id == id, true);
            return ResponseOutput.Result(true);
        }


        /// <summary>
        /// 获取下拉菜单
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<GetTrialClinicalDataSelectOutDto>> GetTrialClinicalDataSelect(GetTrialClinicalDataSelectIndto inDto)
        {
           
            var usedIdsQuery = _readingClinicalDataRepository.Where(x => x.ReadingId == inDto.ReadingId && x.Id != inDto.ReadingClinicalDataId).Select(x => x.ClinicalDataTrialSetId);
            List<GetTrialClinicalDataSelectOutDto> clinicalList = await _clinicalDataTrialSetRepository.Where(x=>x.TrialId==inDto.TrialId&&x.IsConfirm)
                .WhereIf(inDto.UploadRole!=null,x=>x.UploadRole==inDto.UploadRole)
               .Where(x=> !usedIdsQuery.Contains(x.Id))
                .WhereIf(inDto.IsVisit&&inDto.IsBaseLine,x=>x.ClinicalDataLevel == ClinicalLevel.Subject||x.ClinicalDataLevel== ClinicalLevel.SubjectVisit)
                .WhereIf(inDto.IsVisit&&! inDto.IsBaseLine, x => x.ClinicalDataLevel == ClinicalLevel.SubjectVisit)
                .WhereIf(!inDto.IsVisit, x => x.ClinicalDataLevel == ClinicalLevel.Read)
                .Select(x => new GetTrialClinicalDataSelectOutDto()
            {
                ClinicalDataLevel = x.ClinicalDataLevel,
                ClinicalDataSetName = x.ClinicalDataSetName,
                ClinicalUploadType = x.ClinicalUploadType,
                ClinicalDataLevelName = x.ClinicalDataLevel.GetDisplayName(),
                ClinicalUploadTypeName = x.ClinicalUploadType.GetDisplayName(),
                Id = x.Id
            }).ToListAsync() ;
            return clinicalList;
        }


        /// <summary>
        /// 影像阅片临床数据签名
        /// </summary>
        // [HttpPost]
        [NonDynamicMethod]
        public async Task<IResponseOutput> ReadClinicalDataSign(ReadingClinicalDataSignIndto inDto)
        {
            await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.ReadingClinicalDataId, x => new ReadingClinicalData()
            {
                IsSign = true
            });

            var result =await _readingClinicalDataRepository.SaveChangesAsync();

            return ResponseOutput.Result(result);
        }


        /// <summary>
        /// 获取阅片临床数据列表
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<GetReadingClinicalDataListOutDto>> GetReadingClinicalDataList(GetReadingClinicalDataListIndto inDto)
        {
            var isBaseLine = await _subjectVisitRepository.AnyAsync(x => x.Id == inDto.ReadingId && x.IsBaseLine);
            var resultQuery =  _readingClinicalDataRepository.Where(x => x.SubjectId == inDto.SubjectId)
                .Where(x => x.ReadingId == inDto.ReadingId)
                .WhereIf(inDto.UploadRole == UploadRole.CRC, x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
                .WhereIf(inDto.UploadRole == UploadRole.PM && !isBaseLine, x => x.ClinicalDataTrialSet.UploadRole == UploadRole.PM)
                .Select(x => new GetReadingClinicalDataListOutDto() {
                    ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel,
                    SubjectId = x.SubjectId,
                    ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName,
                    ClinicalDataTrialSetId = x.ClinicalDataTrialSetId,
                    IsSign = x.IsSign,
                    ClinicalUploadType = x.ClinicalDataTrialSet.ClinicalUploadType,
                    Id = x.Id,
                    UploadRole=x.ClinicalDataTrialSet.UploadRole,
                    IsCRCUpload = x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC,
                    FileList = x.ReadingClinicalDataPDFList.Select(y => new GetFileDto()
                    {
                        Id = y.Id,
                        FileName = y.FileName,
                        Path = y.Path
                    }).ToList()
                });
                
               


                var result=await resultQuery.ToPagedListAsync(inDto.PageIndex, inDto.PageSize, inDto.SortField == null ? nameof(GetReadingClinicalDataListOutDto.ClinicalDataSetName) : inDto.SortField,
               inDto.Asc);
        
            




            return result;
        }


        /// <summary>
        /// 获取单个阅片临床数据的所有文件
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<GetReadingClinicalDataPDFListOutDto>> GetReadingClinicalDataPDFList(GetReadingClinicalDataPDFListIndto inDto) {

            var result = await _readingClinicalDataPDFRepository.Where(x => x.ReadingClinicalDataId == inDto.ReadingClinicalDataId).ProjectTo<GetReadingClinicalDataPDFListOutDto>(_mapper.ConfigurationProvider)
                .ToPagedListAsync(inDto.PageIndex, inDto.PageSize, inDto.SortField == null ? nameof(GetReadingClinicalDataPDFListOutDto.FileName) : inDto.SortField,
                inDto.Asc);
            return result;
        }

        /// <summary>
        /// 删除PDF单个文件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id:guid}")]
        public async Task<IResponseOutput> DeleteReadingClinicalDataPDF(Guid id)
        {
            await _readingClinicalDataPDFRepository.DeleteFromQueryAsync(x => x.Id == id, true);
            return ResponseOutput.Result(true);
        }


    }
}