using EasyCaching.Core;
using FellowOakDicom;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit;
using MathNet.Numerics;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
    public interface IDownloadAndUploadService
    {
        Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true);
    }
    [ApiExplorerSettings(GroupName = "Trial")]
    public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
    {
        private readonly IEasyCachingProvider _provider;
        private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
        private readonly IRepository<VisitTask> _visitTaskRepository;
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
        private readonly IOSSService _oSSService;
        private readonly IRepository<StudyMonitor> _studyMonitorRepository;
        private readonly IDistributedLockProvider _distributedLockProvider;
        public DownloadAndUploadService(IEasyCachingProvider provider, IRepository<SystemAnonymization> systemAnonymizationRepository, IRepository<SubjectVisit> subjectVisitRepository, IOSSService oSSService,
            IRepository<StudyMonitor> studyMonitorRepository, IDistributedLockProvider distributedLockProvider, IRepository<VisitTask> visitTaskRepository)
        {
            _systemAnonymizationRepository = systemAnonymizationRepository;

            _subjectVisitRepository = subjectVisitRepository;

            _oSSService = oSSService;
            _studyMonitorRepository = studyMonitorRepository;
            _distributedLockProvider = distributedLockProvider;
            _provider = provider;
            _visitTaskRepository = visitTaskRepository;
        }

        /// <summary>
        /// 受试者随机阅片,任务进行随机编号
        /// 进入阅片任务前,随机挑选出该受试者的一个任务,然后给该任务一个编号,编号给的逻辑是:TimePoint Ran+ 已阅任务数量+1
        /// 根据当前受试者该标准已阅任务数量(生效失效的任务都算,考虑重阅,最后编号不重复)  第一个就是TimePoint Ran1,后面依次随机挑选出来的阅片序号依次递增
        /// </summary>
        /// <param name="subjectId"></param>
        /// <param name="trialReadingCriterionId"></param>
        /// <returns></returns>
        public async Task<IResponseOutput> SubejctRandomReadingTaskNameDeal(Guid subjectId, Guid trialReadingCriterionId)
        {
            //subject 随机阅片 才处理任务编号
            if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom))
            {
                //找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
                var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.Id
                   && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskBlindName == "Timepoint" && t.ReadingCategory == ReadingCategory.Visit
                   && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze), true).ToListAsync();

                if (needDealTaskList.Count > 0)
                {
                    //已完成的访视任务数量(包含重阅的)
                    var haveFinishedTaskCount = await _visitTaskRepository.CountAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.Id
                    && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit);

                    //已经处理过的任务名称的数量

                    var haveDealedTaskCount = await _visitTaskRepository.CountAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.Id
                    && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit && t.TaskBlindName != "Timepoint");



                    //随机赋值编号  比如要处理5个任务,实例化一个包含1-5的数组,每次随机取出一个
                    List<int> availableNumbers = Enumerable.Range(haveDealedTaskCount + haveFinishedTaskCount + 1, needDealTaskList.Count).ToList();
                    Random rng = new Random();
                    foreach (var visitTask in needDealTaskList)
                    {
                        int randomIndex = rng.Next(availableNumbers.Count);

                        visitTask.TaskBlindName = $"Timepoint Ran {availableNumbers[randomIndex]}";

                        availableNumbers.RemoveAt(randomIndex);
                    }
                    await _visitTaskRepository.SaveChangesAsync();
                }
            }
            return ResponseOutput.Ok();
        }

        /// <summary>
        /// 获取该受试者任务上传列表(展示已上传情况)
        /// </summary>
        /// <param name="subjectId"></param>
        /// <param name="trialReadingCriterionId"></param>
        /// <returns></returns>
        public async Task<IResponseOutput<List<SubjectImageUploadDTO>>> GetSubjectImageUploadList(Guid subjectId, Guid trialReadingCriterionId)
        {
            await SubejctRandomReadingTaskNameDeal(subjectId, trialReadingCriterionId);

            var query = _repository.Where<VisitTask>(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.SourceSubjectVisitId != null
            && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect)
                .Select(u => new SubjectImageUploadDTO()
                {
                    VisitTaskId = u.Id,

                    SubejctId = u.SubjectId,

                    TrialSiteId = u.Subject.TrialSiteId,

                    IsImageFilter = u.TrialReadingCriterion.IsImageFilter,

                    CriterionModalitys = u.TrialReadingCriterion.CriterionModalitys,

                    SubjectCode = u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code,
                    TaskBlindName = u.TaskBlindName,
                    TaskName = u.TaskName,

                    SourceSubjectVisitId = u.SourceSubjectVisitId,
                    PackState = u.SourceSubjectVisit.PackState,

                    OrginalStudyList = u.SourceSubjectVisit.StudyList
                    .Where(t => u.TrialReadingCriterion.IsImageFilter ? ("|" + u.TrialReadingCriterion.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
                    .Select(t => new StudyBasicInfo()
                    {
                        Id = t.Id,
                        StudyInstanceUid = t.StudyInstanceUid,
                        ModalityForEdit = t.ModalityForEdit,
                        BodyPartExamined = t.BodyPartExamined,
                        BodyPartForEdit = t.BodyPartForEdit,

                        StudyCode = t.StudyCode,
                        StudyTime = t.StudyTime,
                        Description = t.Description,
                        InstanceCount = t.InstanceCount,
                        Modalities = t.Modalities,
                        SeriesCount = t.SeriesCount,
                    }).ToList(),

                    UploadStudyList = u.TaskStudyList.Select(t => new StudyBasicInfo()
                    {
                        Id = t.Id,
                        StudyInstanceUid = t.StudyInstanceUid,
                        ModalityForEdit = t.ModalityForEdit,
                        BodyPartExamined = t.BodyPartExamined,
                        BodyPartForEdit = t.BodyPartForEdit,

                        StudyCode = t.StudyCode,
                        StudyTime = t.StudyTime,
                        Description = t.Description,
                        InstanceCount = t.InstanceCount,
                        Modalities = t.Modalities,
                        SeriesCount = t.SeriesCount,

                        SopInstanceUidList = t.InstanceList.Select(t => t.SopInstanceUid).ToList(),

                    }).ToList()
                })
                ;

            var list = await query.ToListAsync();

            return ResponseOutput.Ok(list);
        }

        private void SpecialArchiveStudyDeal(TaskStudy study)
        {
            #region 特殊逻辑


            if (study.PatientBirthDate.Length == 8)
            {
                study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}";
            }

            var dicModalityList = _repository.Where<Dictionary>(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();


            var modality = study.Modalities;

            var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;

            if (modality == "MR")
            {
                modalityForEdit = "MRI";
            }

            if (modality == "PT")
            {
                modalityForEdit = "PET";
            }
            if (modality == "PT、CT")
            {
                modalityForEdit = "PET-CT";
            }

            study.ModalityForEdit = modalityForEdit;
            #endregion
        }





        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]

        public async Task<IResponseOutput> PreArchiveDicomStudy(PriArchiveTaskStudyCommand preArchiveStudyCommand)
        {

            var studyMonitor = new StudyMonitor()
            {
                TrialId = preArchiveStudyCommand.TrialId,
                SubjectId = preArchiveStudyCommand.SubjectId,
                SubjectVisitId = preArchiveStudyCommand.SubjectVisitId,

                IsSuccess = false,
                UploadStartTime = DateTime.Now,
                IsDicom = true,
                IP = _userInfo.IP,

                IsDicomReUpload = preArchiveStudyCommand.IsDicomReUpload,
                FileSize = preArchiveStudyCommand.FileSize,
                FileCount = preArchiveStudyCommand.FileCount,

            };


            var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);

            return ResponseOutput.Ok(addEntity.Id);

        }

        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> AddOrUpdateArchiveTaskStudy(TaskArchiveStudyCommand incommand)
        {
            #region 获取该subject 已生成任务的访视的检查

            var queryStudy = _repository.Where<VisitTask>(t => t.SubjectId == incommand.SubjectId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id).Select(u => new
            {
                VisitTaskId = u.Id,
                SourceSubjectVisitId = u.SourceSubjectVisitId,
                OrginalStudyList = u.SourceSubjectVisit.StudyList.Select(t => new StudyBasicInfo()
                {
                    Id = t.Id,
                    StudyInstanceUid = t.StudyInstanceUid
                }).ToList(),
            });

            var studyList = await queryStudy.ToListAsync();


            var findOriginStudy = studyList.FirstOrDefault(c => c.OrginalStudyList.Any(t => t.StudyInstanceUid == incommand.Study.StudyInstanceUid));

            if (findOriginStudy == null)
            {
                return ResponseOutput.NotOk("该检查不属于该受试者,请核查");
            }

            #endregion



            var modalitys = string.Empty;

            try
            {
                var trialId = incommand.TrialId;


                var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId);
                studyMonitor.UploadFinishedTime = DateTime.Now;
                studyMonitor.ArchiveFinishedTime = DateTime.Now;
                studyMonitor.FailedFileCount = incommand.FailedFileCount;
                studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
                studyMonitor.RecordPath = incommand.RecordPath;

                //上传
                if (studyMonitor.IsDicomReUpload == false)
                {
                    var study = _mapper.Map<TaskStudy>(incommand.Study);

                    var @lock = _distributedLockProvider.CreateLock($"StudyCode");

                    using (await @lock.AcquireAsync())
                    {
                        //查询数据库获取最大的Code 没有记录则为0
                        var dbStudyCodeIntMax = _repository.Where<TaskStudy>(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();

                        //获取缓存中的值 并发的时候,需要记录,已被占用的值 这样其他线程在此占用的最大的值上递增
                        var cacheMaxCodeInt = _provider.Get<int>($"{trialId}_{StaticData.CacheKey.StudyMaxCode}").Value;

                        int currentNextCodeInt = cacheMaxCodeInt > dbStudyCodeIntMax ? cacheMaxCodeInt + 1 : dbStudyCodeIntMax + 1;
                        study.Code = currentNextCodeInt;

                        study.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy));

                        _provider.Set<int>($"{trialId}_{StaticData.CacheKey.StudyMaxCode}", study.Code, TimeSpan.FromMinutes(30));

                    }


                    study.Id = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());
                    study.TrialId = incommand.TrialId;
                    study.SubjectId = incommand.SubjectId;
                    study.VisitTaskId = findOriginStudy.VisitTaskId;
                    //study.SubjectVisitId = incommand.SubjectVisitId;


                    //特殊处理逻辑
                    study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Distinct());
                    SpecialArchiveStudyDeal(study);
                    modalitys = study.Modalities;

                    await _repository.AddAsync(study);


                    studyMonitor.StudyId = study.Id;
                    studyMonitor.StudyCode = study.StudyCode;


                    foreach (var seriesItem in incommand.Study.SeriesList)
                    {
                        var series = _mapper.Map<TaskSeries>(seriesItem);

                        series.Id = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());
                        series.StudyId = study.Id;

                        series.TrialId = incommand.TrialId;
                        series.SubjectId = incommand.SubjectId;
                        //series.SubjectVisitId = incommand.SubjectVisitId;
                        series.VisitTaskId = findOriginStudy.VisitTaskId;

                        //前端传递的数量不准,上传的时候,把失败的也加进来了,以实际数组的数字为准
                        series.InstanceCount = seriesItem.InstanceList.Count;

                        await _repository.AddAsync(series);

                        foreach (var instanceItem in seriesItem.InstanceList)
                        {
                            var isntance = _mapper.Map<TaskInstance>(instanceItem);

                            Guid instanceId = IdentifierHelper.CreateGuid(study.StudyInstanceUid, series.SeriesInstanceUid, isntance.SopInstanceUid, study.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());

                            isntance.Id = instanceId;
                            isntance.StudyId = study.Id;
                            isntance.SeriesId = series.Id;

                            isntance.TrialId = incommand.TrialId;
                            isntance.SubjectId = incommand.SubjectId;
                            //isntance.SubjectVisitId = incommand.SubjectVisitId;
                            isntance.VisitTaskId = findOriginStudy.VisitTaskId;

                            await _repository.AddAsync(isntance);
                        }
                    }




                }
                else
                {

                    var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), findOriginStudy.VisitTaskId.ToString());

                    var study = await _repository.FirstOrDefaultAsync<TaskStudy>(t => t.Id == studyId);

                    //重传的时候也要赋值检查Id
                    studyMonitor.StudyId = study.Id;
                    studyMonitor.StudyCode = study.StudyCode;

                    //特殊处理逻辑
                    study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
                    SpecialArchiveStudyDeal(study);
                    modalitys = study.Modalities;


                    // 少了整个序列

                    //某个序列下少了instance
                    foreach (var seriesItem in incommand.Study.SeriesList)
                    {
                        var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString(), findOriginStudy.VisitTaskId.ToString());

                        TaskSeries dicomSeries = await _repository.FirstOrDefaultAsync<TaskSeries>(t => t.Id == seriesId);

                        //判断重复
                        if (dicomSeries == null)
                        {
                            var series = _mapper.Map<TaskSeries>(seriesItem);

                            series.Id = seriesId;
                            series.StudyId = study.Id;

                            series.TrialId = incommand.TrialId;
                            series.SubjectId = incommand.SubjectId;
                            series.VisitTaskId = findOriginStudy.VisitTaskId;
                            //series.SubjectVisitId = incommand.SubjectVisitId;


                            dicomSeries = await _repository.AddAsync(series);

                            //新的序列 那么  检查的序列数量+1
                            study.SeriesCount += 1;
                        }
                        else
                        {
                            //该序列掉了instance
                            dicomSeries.InstanceCount += seriesItem.InstanceList.Count;
                        }

                        foreach (var instanceItem in seriesItem.InstanceList)
                        {
                            var insntance = _mapper.Map<TaskInstance>(instanceItem);
                            insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString(), findOriginStudy.VisitTaskId.ToString());
                            insntance.StudyId = study.Id;
                            insntance.SeriesId = dicomSeries.Id;

                            insntance.TrialId = incommand.TrialId;
                            insntance.SubjectId = incommand.SubjectId;
                            insntance.VisitTaskId = findOriginStudy.VisitTaskId;

                            await _repository.AddAsync(insntance);
                        }


                        //  不管是新的序列  还是 该序列 掉了Instance   重传的时候 检查的instance 数量都会增加
                        study.InstanceCount += seriesItem.InstanceList.Count;

                    }


                }

                var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit");

                using (await @lock2.AcquireAsync())
                {
                    await _repository.SaveChangesAsync();
                }
            }
            catch (Exception ex)
            {

                return ResponseOutput.NotOk(ex.Message);
            }
            finally
            {
                _provider.Remove($"StudyUid_{incommand.TrialId}_{incommand.Study.StudyInstanceUid}");
            }







            return ResponseOutput.Ok(modalitys);
        }


        [HttpDelete]
        public async Task<IResponseOutput> DeleteTaskStudy(Guid visitTaskId)
        {

            await _repository.BatchDeleteAsync<TaskStudy>(t => t.VisitTaskId == visitTaskId);
            await _repository.BatchDeleteAsync<TaskSeries>(t => t.VisitTaskId == visitTaskId);
            await _repository.BatchDeleteAsync<TaskInstance>(t => t.VisitTaskId == visitTaskId);

            return ResponseOutput.Ok();
        }
        /// <summary>
        /// 打包和匿名化影像 默认是匿名化打包,也可以不匿名化打包
        /// </summary>
        /// <param name="trialId"></param>
        /// <param name="subjectVisitId"></param>
        /// <param name="isDicom"></param>
        /// <param name="isAnonymize"></param>
        /// <returns></returns>

        public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
        {


            var extralConfig = _repository.Where<Trial>(t => t.Id == trialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;

            var config = JsonConvert.DeserializeObject<TrialExtraConfig>(extralConfig) ?? new TrialExtraConfig();

            if (config.IsSupportQCDownloadImage == false)
            {
                throw new BusinessValidationFailedException("该项目不支持QC下载影像");
            }

            var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);

            var sujectCode = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.Subject.Code).FirstOrDefaultAsync();

            var packState = isDicom ? subjectVisit.PackState : subjectVisit.NoDicomPackState;

            if (packState == PackState.WaitPack)
            {

                if (isDicom)
                {
                    subjectVisit.PackState = PackState.Packing;
                    HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, true, isAnonymize), TimeSpan.FromSeconds(1));

                }
                else
                {
                    subjectVisit.NoDicomPackState = PackState.Packing;

                    HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, false, isAnonymize), TimeSpan.FromSeconds(1));
                }


                await _subjectVisitRepository.SaveChangesAsync();
            }

            return ResponseOutput.Ok(isDicom ? subjectVisit.VisitImageZipPath : subjectVisit.VisitNoDicomImageZipPath,
                new { FileName = $"{sujectCode}_{subjectVisit.VisitName}_ImageStudy_{(isDicom ? "Dicom" : "NoneDicom")}.zip" });

        }



        /// <summary>
        /// 受试者级别所有的影像
        /// 访视级别的影响 传递subjectVisitId
        /// 标准Id是可选的  不同标准有些检查可能有过滤
        /// </summary>
        /// <param name="_subjectRepository"></param>
        /// <param name="inQuery"></param>
        /// <returns></returns>
        public async Task<IResponseOutput> GetSubejectOrVisitZipInfo([FromServices] IRepository<Subject> _subjectRepository, SubejctZipInfoQuery inQuery)
        {
            var isImageFilter = false;

            var criterionModalitys = string.Empty;

            if (inQuery.TrialReadingCriterionId != null)
            {
                var criterionInfo = await _repository.Where<ReadingQuestionCriterionTrial>(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstOrDefaultAsync();

                if (criterionInfo != null)
                {
                    isImageFilter = criterionInfo.IsImageFilter;
                    criterionModalitys = criterionInfo.CriterionModalitys;
                }

            }

            if (inQuery.SubejectVisitId != null)
            {
                var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubejectVisitId)


                            select new
                            {
                                SubjectCode = sv.Subject.Code,
                                VisitName = sv.VisitName,
                                StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
                                .Select(u => new
                                {
                                    u.PatientId,
                                    u.StudyTime,
                                    u.StudyCode,

                                    SeriesList = u.SeriesList.Select(z => new
                                    {
                                        z.Modality,

                                        InstancePathList = z.DicomInstanceList.Select(k => new
                                        {
                                            k.Path
                                        })
                                    })

                                }),

                                NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
                                .Select(nd => new
                                {
                                    nd.Modality,
                                    nd.StudyCode,
                                    nd.ImageDate,

                                    FileList = nd.NoneDicomFileList.Select(file => new
                                    {
                                        file.FileName,
                                        file.Path,
                                        file.FileType
                                    })
                                })
                            };

                var result = query.ToList();

                return ResponseOutput.Ok(result);
            }
            else if (inQuery.SubejctId != null)
            {
                var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubejctId).SelectMany(t=>t.SubjectVisitList)


                            select new
                            {
                                SubjectCode = sv.Subject.Code,
                                VisitName = sv.VisitName,
                                StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|"))
                                .Select(u => new
                                {
                                    u.PatientId,
                                    u.StudyTime,
                                    u.StudyCode,

                                    SeriesList = u.SeriesList.Select(z => new
                                    {
                                        z.Modality,

                                        InstancePathList = z.DicomInstanceList.Select(k => new
                                        {
                                            k.Path
                                        })
                                    })

                                }),

                                NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|"))
                                .Select(nd => new
                                {
                                    nd.Modality,
                                    nd.StudyCode,
                                    nd.ImageDate,

                                    FileList = nd.NoneDicomFileList.Select(file => new
                                    {
                                        file.FileName,
                                        file.Path,
                                        file.FileType
                                    })
                                })
                            };

                var result = query.ToList();

                return ResponseOutput.Ok(result);
            }
            else
            {
                return ResponseOutput.NotOk("不允许 subjectId  subjectId 都不传递");
            }


        }

        /// <summary>
        /// 后台任务调用,前端忽略该接口
        /// </summary>
        /// <param name="trialId"></param>
        /// <param name="subjectVisitId"></param>
        /// <param name="isDicom"></param>
        /// <param name="isAnonymize"></param>
        /// <returns></returns>
        public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
        {

            var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);

            try
            {
                var addOrUpdateFixedFieldList = new List<SystemAnonymization>();

                var ircFieldList = new List<SystemAnonymization>();

                if (isAnonymize)
                {
                    var systemAnonymizationList = _systemAnonymizationRepository.Where(t => t.IsEnable).ToList();

                    addOrUpdateFixedFieldList = systemAnonymizationList.Where(t => t.IsFixed).ToList();

                    ircFieldList = systemAnonymizationList.Where(t => t.IsFixed == false).ToList();
                }

                var subjectAndVisitInfo = _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { SubjectCode = t.Subject.Code, t.Trial.TrialCode, t.VisitNum }).FirstOrDefault();

                var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId)

                            select new
                            {
                                SubjectCode = sv.Subject.Code,
                                VisitName = sv.VisitName,
                                StudyList = sv.StudyList.Select(u => new
                                {
                                    u.PatientId,
                                    u.StudyTime,
                                    u.StudyCode,

                                    SeriesList = u.SeriesList.Select(z => new
                                    {
                                        z.Modality,

                                        InstancePathList = z.DicomInstanceList.Select(k => new
                                        {
                                            k.Path
                                        })
                                    })

                                }),

                                NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new
                                {
                                    nd.Modality,
                                    nd.StudyCode,
                                    nd.ImageDate,

                                    FileList = nd.NoneDicomFileList.Select(file => new
                                    {
                                        file.FileName,
                                        file.Path,
                                        file.FileType
                                    })
                                })
                            };

                var info = query.FirstOrDefault();

                if (info != null)
                {
                    // 创建一个临时文件夹来存放文件
                    string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
                    Directory.CreateDirectory(tempFolderPath);

                    //dicom  处理

                    if (isDicom)
                    {
                        // 遍历查询结果
                        foreach (var studyInfo in info.StudyList)
                        {
                            // 遍历 Series
                            foreach (var seriesInfo in studyInfo.SeriesList)
                            {
                                string studyDicomFolderPath = Path.Combine(tempFolderPath, "Dicom",/* $"{info.SubjectCode}_{info.VisitName}",*/ $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");

                                // 创建 影像 文件夹
                                Directory.CreateDirectory(studyDicomFolderPath);

                                // 遍历 InstancePathList
                                foreach (var instanceInfo in seriesInfo.InstancePathList)
                                {
                                    // 复制文件到相应的文件夹
                                    string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path));

                                    //下载到当前目录
                                    await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);

                                    #region 匿名化逻辑


                                    if (isAnonymize)
                                    {
                                        //受试者随机阅片,需要匿名化检查时间
                                        DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
                                        DicomDataset dataset = dicomFile.Dataset;
                                        dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
                                        dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);

                                        #region 前端已经匿名化,不需要做相关tag匿名化
                                        //DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);

                                        //DicomDataset dataset = dicomFile.Dataset;

                                        //foreach (var item in addOrUpdateFixedFieldList)
                                        //{

                                        //    var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));

                                        //    dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
                                        //}

                                        //foreach (var item in ircFieldList)
                                        //{

                                        //    var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));

                                        //    if (dicomTag == DicomTag.ClinicalTrialProtocolID)
                                        //    {
                                        //        dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);

                                        //    }
                                        //    if (dicomTag == DicomTag.ClinicalTrialSiteID)
                                        //    {
                                        //        //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);

                                        //    }
                                        //    if (dicomTag == DicomTag.ClinicalTrialSubjectID)
                                        //    {
                                        //        dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);

                                        //    }
                                        //    if (dicomTag == DicomTag.ClinicalTrialTimePointID)
                                        //    {
                                        //        dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());

                                        //    }
                                        //    if (dicomTag == DicomTag.PatientID)
                                        //    {
                                        //        dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);

                                        //    }

                                        //}
                                        #endregion

                                    }
                                    #endregion
                                }
                            }
                        }


                        var zipDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_Dicom.zip");
                        ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "Dicom"), zipDicomPath);
                        //上传到Oss
                        var relativeDicomPath = await _oSSService.UploadToOSSAsync(zipDicomPath, $"download_zip", false);

                        await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativeDicomPath });


                        File.Delete(zipDicomPath);
                    }
                    else
                    {
                        var relativeNoneDicomPath = string.Empty;

                        if (info.NoneDicomStudyList.Count() == 1 && info.NoneDicomStudyList.SelectMany(t => t.FileList).Count() == 1)
                        {
                            relativeNoneDicomPath = info.NoneDicomStudyList.First().FileList.First().Path;
                        }
                        else
                        {
                            //非dicom 处理

                            foreach (var noneDicomStudy in info.NoneDicomStudyList)
                            {
                                string studyNoneDicomFolderPath = Path.Combine(tempFolderPath, "NoneDicom", /*$"{info.SubjectCode}_{info.VisitName}",*/ $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");

                                Directory.CreateDirectory(studyNoneDicomFolderPath);

                                foreach (var file in noneDicomStudy.FileList)
                                {
                                    string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));

                                    //下载到当前目录
                                    await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath);
                                }
                            }

                            var zipNoneDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_NoneDicom.zip");
                            ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "NoneDicom"), zipNoneDicomPath);
                            relativeNoneDicomPath = await _oSSService.UploadToOSSAsync(zipNoneDicomPath, $"download_zip", false);

                            File.Delete(zipNoneDicomPath);
                        }

                        await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitNoDicomImageZipPath = relativeNoneDicomPath });


                    }

                    //清理文件夹
                    Directory.Delete(tempFolderPath, true);

                }
            }
            catch (Exception ex)
            {
                await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.WaitPack });

            }





        }

    }
}