using AutoMapper;
using EasyCaching.Core;
using ExcelDataReader;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Domain.Share.Reading;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Magicodes.ExporterAndImporter.Excel;
using MassTransit;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using MiniExcelLibs;
using Newtonsoft.Json;
using SharpCompress.Archives;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IRaCIS.Core.API.Controllers
{

    #region 上传基类封装
    [DisableFormValueModelBinding]
    public abstract class UploadBaseController : ControllerBase
    {
        /// <summary>  流式上传  直接返回</summary>
        [Route("base")]
        public virtual async Task<IResponseOutput> SingleFileUploadAsync(Func<string, (string, string)> filePathFunc)
        {
            var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;

            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {

                    var (serverFilePath, relativePath) = filePathFunc(contentDisposition.FileName.Value);

                    await FileStoreHelper.WriteFileAsync(section.Body, serverFilePath);

                    //仅仅返回一个文件,如果多文件上传  在最后返回多个路径
                    return ResponseOutput.Ok(new
                    {
                        FilePath = relativePath,
                        FullFilePath = relativePath /*+ "?access_token=" + _userInfo.UserToken*/
                    });

                }
                section = await reader.ReadNextSectionAsync();
            }
            return ResponseOutput.Ok();
        }


        /// <summary>  流式上传   通用封装 不返回任何数据,后续还有事情处理 </summary>
        [Route("base")]
        public virtual async Task FileUploadAsync(Func<string, Task<string>> filePathFunc)
        {
            var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;

            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {

                    var fileName = contentDisposition.FileName.Value;


                    //处理压缩文件
                    if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
                    {
                        var archive = ArchiveFactory.Open(section.Body);

                        foreach (var entry in archive.Entries)
                        {
                            if (!entry.IsDirectory)
                            {

                                var serverFilePath = await filePathFunc(entry.Key);

                                entry.WriteToFile(serverFilePath);

                            }
                        }
                    }
                    //普通单个文件
                    else
                    {
                        var serverFilePath = await filePathFunc(fileName);

                        await FileStoreHelper.WriteFileAsync(section.Body, serverFilePath);

                    }



                }
                section = await reader.ReadNextSectionAsync();
            }
        }



        /// <summary>  流式上传   Dicom上传  </summary>
        [Route("base")]
        public virtual async Task<int> DicomFileUploadAsync(Func<string, Stream, Task> filePathFunc)
        {

            var fileCount = 0;
            var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;

            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {

                    var fileName = contentDisposition.FileName.Value ?? String.Empty;

                    string mediaType = section.ContentType ?? String.Empty;


                    //处理压缩文件
                    if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
                    {
                        var archive = ArchiveFactory.Open(section.Body);

                        foreach (var entry in archive.Entries)
                        {
                            if (!entry.IsDirectory)
                            {
                                ++fileCount;

                                await filePathFunc(entry.Key, entry.OpenEntryStream());
                            }
                        }
                    }
                    //普通单个文件
                    else
                    {
                        if (mediaType.Contains("octet-stream"))
                        {
                            ++fileCount;

                            await filePathFunc(fileName, section.Body);
                        }

                    }
                }
                section = await reader.ReadNextSectionAsync();
            }

            return fileCount;
        }


    }

    #endregion

    #region Dicom 影像上传  临床数据  非diocm 

    [ApiExplorerSettings(GroupName = "Image")]
    [ApiController]
    public class StudyController : UploadBaseController
    {
        public IMapper _mapper { get; set; }
        public IUserInfo _userInfo { get; set; }
        private readonly IMediator _mediator;
        private readonly IRepository<ClinicalData> _clinicalDataRepository;
        private readonly IWebHostEnvironment _hostEnvironment;

        private readonly IRepository _repository;


        public StudyController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator,
             IRepository<ClinicalData> clinicalDataRepository,
            IRepository repository)
        {
            _hostEnvironment = hostEnvironment;
            _mediator = mediator;
            this._clinicalDataRepository = clinicalDataRepository;
            _mapper = mapper;
            _userInfo = userInfo;
            _repository = repository;
        }


        /// <summary>Dicom 归档</summary>
        [HttpPost, Route("Study/ArchiveStudy/{trialId:guid}")]
        [DisableFormValueModelBinding]
        [DisableRequestSizeLimit]
        [TypeFilter(typeof(TrialResourceFilter))]
        public async Task<IResponseOutput> ArchiveStudyNew([FromForm] ArchiveStudyCommand archiveStudyCommand,
            [FromServices] ILogger<UploadDownLoadController> _logger,
             [FromServices] IEasyCachingProvider _provider,
            [FromServices] IStudyService _studyService,
           [FromServices] IDicomArchiveService _dicomArchiveService,
            [FromServices] IRepository _repository
            )
        {

            string studycode = string.Empty;

            var startTime = DateTime.Now;

            if (_provider.Exists("StudyUid_" + archiveStudyCommand.StudyInstanceUid))
            {
                return ResponseOutput.NotOk("当前已有人正在上传和归档该检查!");
            }
            else
            {
                _provider.Set("StudyUid_" + archiveStudyCommand.StudyInstanceUid, _userInfo.Id, TimeSpan.FromMinutes(30));
            }

            var (archiveResult, archivedStudyIds) = (new DicomArchiveResult(), new List<Guid>());


            var (seriesInstanceUidList, sopInstanceUidList) = (new List<string>(), new List<string>());

            //重传的时候,找出当前检查已经上传的series instance
            if (archiveStudyCommand.AbandonStudyId != null)
            {
                (seriesInstanceUidList, sopInstanceUidList) = _studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value);
            }

            var savedInfo = _studyService.GetSaveToDicomInfo(archiveStudyCommand.SubjectVisitId);

            archiveResult.ReceivedFileCount = await DicomFileUploadAsync(async (fileName, fileStream) =>
             {

                 try
                 {
                     using (var memoryStream = new MemoryStream())
                     {
                         await fileStream.CopyToAsync(memoryStream);

                         memoryStream.Seek(0, SeekOrigin.Begin);

                         var (studyId, studyCode) = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
                         if (!archivedStudyIds.Contains(studyId))
                         {
                             archivedStudyIds.Add(studyId);
                             archiveResult.ArchivedDicomStudies.Add(new DicomStudyBasicDTO() { StudyCode = studyCode, Id = studyId });
                         }
                     }


                 }
                 catch (Exception e)
                 {
                     _logger.LogError(e.Message + e.StackTrace);

                     archiveResult.ErrorFiles.Add(fileName);

                     _provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);

                 }


             });


            try
            {
                if (archivedStudyIds.Count > 0) // 上传成功,处理逻辑
                {

                    // 同一个访视 多个线程上传处理  批量保存 可能造成死锁 https://www.cnblogs.com/johnblogs/p/9945767.html

                    await _dicomArchiveService.DicomDBDataSaveChange();

                    archiveResult.ReuploadNewStudyId = archivedStudyIds[0] == archiveStudyCommand.AbandonStudyId ? archivedStudyIds[0] : Guid.Empty;

                    await _repository.AddAsync(new StudyMonitor()
                    {
                        TrialId = savedInfo.TrialId,
                        SiteId = savedInfo.SiteId,
                        SubjectId = savedInfo.SubjectId,
                        SubjectVisitId = savedInfo.SubjectVisitId,
                        StudyId = archivedStudyIds[0],

                        StudyCode = studycode,
                        UploadStartTime = startTime,
                        UploadFinishedTime = DateTime.Now,
                        FileSize = (decimal)HttpContext.Request.ContentLength,
                        FileCount = archiveResult.ReceivedFileCount,
                        IsDicom = true,
                        IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
                        IP = _userInfo.IP
                    }, true);


                    //_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, );

                    _provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);

                }
                else
                {
                    return ResponseOutput.NotOk(archiveResult);
                }


            }
            catch (Exception e)
            {

                _logger.LogError(e.Message + e.StackTrace);

                _provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);

                return ResponseOutput.NotOk(e.Message, ApiResponseCodeEnum.ProgramException);

            }

            return ResponseOutput.Ok(archiveResult);



        }





        /// <summary>
        /// 上传临床数据  多文件
        /// </summary>
        /// <param name="subjectVisitId"></param>
        /// <returns></returns>
        [HttpPost("ClinicalData/UploadVisitClinicalData/{trialId:guid}/{subjectVisitId:guid}")]
        [DisableRequestSizeLimit]
        [Authorize(Policy = IRaCISPolicy.CRC)]
        public async Task<IResponseOutput> UploadVisitClinicalData(Guid subjectVisitId)
        {
            await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
            var sv = _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault().IfNullThrowException();
         
            await FileUploadAsync(async (fileName) =>
            {
                var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetClinicalDataPath(_hostEnvironment, fileName, sv.TrialId, sv.SiteId, sv.SubjectId, subjectVisitId);
                //插入临床pdf 路径
                await _repository.AddAsync(new PreviousPDF() { SubjectVisitId = subjectVisitId,

                    IsVisist=true,
                    DataType= ClinicalDataType.MedicalHistory,
                    UploadType=ClinicalUploadType.PDF,
                    SubjectId= sv.SubjectId,
                    TrialId=sv.TrialId,
                    ClinicalLevel = ClinicalLevel.Subject, Path = relativePath, FileName = fileRealName });
                return serverFilePath;
            });
            await _repository.SaveChangesAsync();
            return ResponseOutput.Ok();

        }

        /// <summary>
        /// 上传临床数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isVisit"></param>
        /// <returns></returns>
        [HttpPost("ClinicalData/UploadClinicalData/{trialId:guid}/{id:guid}/{isVisit:bool}")]
        [DisableRequestSizeLimit]
        public async Task<IResponseOutput> UploadClinicalData(Guid id, bool isVisit)
        {
            var filerelativePath = string.Empty;
            if (isVisit)
            {
                var sv = _repository.Where<SubjectVisit>(t => t.Id == id).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault().IfNullThrowException();
                await FileUploadAsync(async (fileName) =>
                {
                    var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetClinicalDataPath(_hostEnvironment, fileName, sv.TrialId, sv.SiteId, sv.SubjectId, id);
                    //插入临床pdf 路径
                    filerelativePath = relativePath;
                    return serverFilePath;
                });
            }
            else
            {
                var subjectId = await _repository.Where<ReadModule>(x => x.Id == id).Select(x =>
                      x.SubjectId
                ).FirstOrDefaultAsync();
                var subject = await _repository.Where<Subject>(x => x.Id == subjectId).Select(x => new
                {
                    x.TrialId,
                    x.SiteId,
                }).FirstOrDefaultAsync();
                await FileUploadAsync(async (fileName) =>
                {
                    var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetClinicalDataPath(_hostEnvironment, fileName, subject.TrialId, subject.SiteId, subjectId, id);
                    //插入临床pdf 路径
                    filerelativePath = relativePath;
                    return serverFilePath;
                });
            }

            return ResponseOutput.Ok(filerelativePath);
        }
        /// <summary>
        /// 上传非Dicom 文件 支持压缩包 多文件上传
        /// </summary>
        /// <param name="formCollection"></param>
        /// <param name="subjectVisitId"></param>
        /// <param name="noneDicomStudyId"></param>
        /// <returns></returns>
        //[DisableRequestSizeLimit]
        [RequestSizeLimit(1_073_741_824)]
        [HttpPost("NoneDicomStudy/UploadNoneDicomFile/{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyId:guid}")]
        [TypeFilter(typeof(TrialResourceFilter))]
        [Authorize(Policy = IRaCISPolicy.CRC)]
        public async Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId)
        {
            var startTime = DateTime.Now;

            await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);

            var sv = (await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();


            await FileUploadAsync(async (fileName) =>
            {

                var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetNoneDicomFilePath(_hostEnvironment, fileName, sv.TrialId, sv.SiteId, sv.SubjectId, subjectVisitId);

                await _repository.AddAsync(new NoneDicomStudyFile() { FileName = fileRealName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });

                return serverFilePath;
            });



            //// 上传非Dicom 后  将状态改为待提交 分为普通上传 和QC后重传  普通上传时才改为待提交
            //await _repository.UpdatePartialFromQueryAsync<SubjectVisit>(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit });

            var studyCode = await _repository.Where<NoneDicomStudy>(t => t.Id == noneDicomStudyId).Select(t => t.StudyCode).FirstOrDefaultAsync();

            await _repository.AddAsync(new StudyMonitor()
            {
                FileCount = formCollection.Files.Count,
                FileSize = formCollection.Files.Sum(t => t.Length),
                IsDicom = false,
                IsDicomReUpload = false,
                StudyId = noneDicomStudyId,
                StudyCode = studyCode,
                UploadStartTime = startTime,
                UploadFinishedTime = DateTime.Now,
                IP = _userInfo.IP,
                TrialId = sv.TrialId,
                SiteId = sv.SiteId,
                SubjectId = sv.SubjectId,
                SubjectVisitId = subjectVisitId,
            });

            await _repository.SaveChangesAsync();

            return ResponseOutput.Ok();
        }




        /// <summary>
        /// 一致性核查 excel上传 支持三种格式
        /// </summary>
        /// <param name="trialId"></param>
        /// <returns></returns>
        [HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
        [TypeFilter(typeof(TrialResourceFilter))]
        [Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId   )
        {
                   
            var (serverFilePath, relativePath, fileName) = (string.Empty, string.Empty, string.Empty);
            await FileUploadAsync(async (realFileName) =>
            {
                fileName = realFileName;

                if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls"))
                {
                    throw new BusinessValidationFailedException("支持.xlsx、.xls、.csv格式的文件上传。");
                }

                (serverFilePath, relativePath) = FileStoreHelper.GetTrialCheckFilePath(_hostEnvironment, fileName, trialId);

                await _repository.AddAsync(new ConsistencyCheckFile()
                {
                    TrialId = trialId,
                    CreateTime = DateTime.Now,
                    FileName = fileName,
                    FilePath = relativePath,
                    RelativePath = relativePath,
                    CreateUserId = _userInfo.Id
                });

                return serverFilePath;
            });




            var etcCheckList = new List<CheckViewModel>();



            #region MiniExcel  需要自己验证数据格式规范

            //if (fileName.EndsWith(".csv"))
            //{
            //    //因为csv 需要加配置文件 不然都是null
            //    etcCheckList = MiniExcel.Query<CheckViewModel>(filePath, null, configuration: config).ToList();
            //}
            //else if (fileName.EndsWith(".xlsx"))
            //{
            //    


            //    etcCheckList = MiniExcel.Query<CheckViewModel>(filePath).ToList();
            //}

            #endregion

            //Magicodes 支持自定义特性验证
            if (fileName.EndsWith(".xlsx"))
            {
                var Importer = new ExcelImporter();

                var import = await Importer.Import<CheckViewModel>(System.IO.File.OpenRead(serverFilePath));

                if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());

                if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));

                if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));

                etcCheckList = import.Data.ToList();
            }
            else if (fileName.EndsWith(".csv"))
            {
                #region   临时方案   MiniExcel读取  然后保存为xlsx  再用 Magicodes验证数据

                //因为csv 需要加配置文件 不然都是null
                etcCheckList = MiniExcel.Query<CheckViewModel>(serverFilePath, null, configuration: new MiniExcelLibs.Csv.CsvConfiguration()
                {
                    StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
                }).ToList();

                var (csVToXlsxPath, csVToXlsxRelativePath) = FileStoreHelper.GetTrialCheckFilePath(_hostEnvironment, Path.GetFileNameWithoutExtension(fileName) + ".xlsx", trialId);


                await MiniExcel.SaveAsAsync(csVToXlsxPath, etcCheckList, excelType: ExcelType.XLSX);


                var Importer = new ExcelImporter();

                var import = await Importer.Import<CheckViewModel>(System.IO.File.OpenRead(csVToXlsxPath));

                if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());

                if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));

                if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));

                etcCheckList = import.Data.ToList();

                #endregion


                #region 导入组件有问题  excel编码格式
                //var Importer = new CsvImporter();

                //var import = await Importer.Import<CheckViewModel>(File.OpenRead(filePath));

                //if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());

                //if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));

                //if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));

                //etcCheckList = import.Data.ToList();
                #endregion

            }
            //ExcelReaderFactory  需要自己验证数据 并且从固定列取数据
            else
            {
                //为了支持 xls  引入新的组件库
                using (var stream = System.IO.File.Open(serverFilePath, FileMode.Open, FileAccess.Read))
                {
                    // Auto-detect format, supports:
                    //  - Binary Excel files (2.0-2003 format; *.xls)
                    //  - OpenXml Excel files (2007 format; *.xlsx, *.xlsb)
                    using (var reader = ExcelReaderFactory.CreateReader(stream))
                    {

                        // 2. Use the AsDataSet extension method
                        var dateset = reader.AsDataSet();

                        foreach (DataRow col in dateset.Tables[0].Rows)
                        {

                            etcCheckList.Add(new CheckViewModel()
                            {
                                SiteCode = col[0].ToString(),
                                SubjectCode = col[1].ToString(),
                                VisitName = col[2].ToString(),
                                StudyDate = col[3].ToString(),
                                Modality = col[4].ToString(),
                            });
                        }

                        etcCheckList.Remove(etcCheckList[0]);

                        // The result of each spreadsheet is in result.Tables
                    }
                }
            }

            if (etcCheckList == null || etcCheckList.Count == 0)
            {
                return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
            }
            else
            {
                //处理Excel  有时只是清除某些行的数据  读取也会读到数据,只是数据是null   后面处理的时候转为字符串为报错
                etcCheckList.ForEach(t =>
                {
                    t.Modality = t.Modality ?? string.Empty;
                    t.SiteCode = t.SiteCode ?? string.Empty;
                    t.SubjectCode = t.SubjectCode ?? string.Empty;
                    t.VisitName = t.VisitName ?? string.Empty;
                    t.StudyDate = t.StudyDate ?? string.Empty;
                });

                var dt = DateTime.Now;

                etcCheckList = etcCheckList.Where(t => !(t.Modality == string.Empty && t.SiteCode == string.Empty && t.SubjectCode == string.Empty && t.VisitName == string.Empty && t.StudyDate == string.Empty && DateTime.TryParse(t.StudyDate, out dt))).ToList();

                if (etcCheckList.Count == 0)
                {
                    return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
                }

            }


            await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });

            return ResponseOutput.Ok();

        }
    }


    #endregion

    #region 医生文件上传下载

    /// <summary>医生文件上传下载</summary>
    [ApiExplorerSettings(GroupName = "Common")]
    [ApiController]
    public class FileController : UploadBaseController
    {
        public IMapper _mapper { get; set; }
        public IUserInfo _userInfo { get; set; }
       

        private readonly IWebHostEnvironment _hostEnvironment;

        private readonly IFileService _fileService;



        public FileController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment,IFileService fileService)
        {
            _fileService = fileService;
            _hostEnvironment = hostEnvironment;
          
            _mapper = mapper;
            _userInfo = userInfo;
        }

        /// <summary>
        /// 上传文件[FileUpload]
        /// </summary>
        /// <param name="attachmentType">附件类型</param>
        /// <param name="doctorId">医生Id</param>
        /// <returns>返回文件信息</returns>
        [HttpPost, Route("file/UploadFile/{attachmentType}/{doctorId}")]
        [DisableFormValueModelBinding]
        [DisableRequestSizeLimit]
        public async Task<IResponseOutput> UploadOrdinaryFile(string attachmentType, Guid doctorId)
        {

            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetDoctorOrdinaryFilePath(_hostEnvironment, fileName, doctorId, attachmentType));

        }


        /// <summary>
        /// 上传文件( 不是医生个人的文件)[FileUpload]
        /// 例如:阅片章程等
        /// </summary>
        /// <param name="type">文件类型</param>
        /// <returns></returns>

        [HttpPost, Route("file/UploadNonDoctorFile/{type}")]
        [DisableFormValueModelBinding]
        [DisableRequestSizeLimit]
        public async Task<IResponseOutput> UploadNonDoctorFile(string type)
        {
            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetNonDoctorFilePath(_hostEnvironment, fileName, type));
        }


        /// <summary>
        /// 下载多个医生的所有附件
        /// </summary>
        /// <param name="doctorIds"></param>
        /// <returns></returns>

        [HttpPost, Route("file/downloadDoctorAttachments")]
        public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachment(Guid[] doctorIds)
        {

            var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);

            return ResponseOutput.Ok(new UploadFileInfoDTO
            {
                FilePath = path,
                FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)

            });
        }

        /// <summary>
        /// 下载医生官方简历
        /// </summary>
        /// <param name="language"></param>
        /// <param name="doctorIds"></param>
        /// <returns></returns>
        [HttpPost, Route("file/downloadOfficialCV/{language}")]
        public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadOfficialResume(int language, Guid[] doctorIds)
        {

            var path = _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
            return ResponseOutput.Ok(new UploadFileInfoDTO
            {
                FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds),
                FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
            });
        }

        /// <summary>
        /// 下载指定医生的指定附件
        /// </summary>
        /// <param name="doctorId">医生Id</param>
        /// <param name="attachmentIds">要下载的附件Id</param>
        /// <returns></returns>
        [HttpPost, Route("file/downloadByAttachmentId/{doctorId}")]
        public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
        {
            var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds);
            return ResponseOutput.Ok(new UploadFileInfoDTO
            {
                FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds),
                FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
            });
        }




        [HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
        [TypeFilter(typeof(TrialResourceFilter))]
        [AllowAnonymous]
        public async Task<IResponseOutput<string>> DownloadResume( int language, Guid trialId, Guid[] doctorIdArray)
        {
            var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);

            return ResponseOutput.Ok(zipPath);
        }
    }
    #endregion


    #region 项目 系统  基本文件 上传  下载 预览

    [ApiExplorerSettings(GroupName = "Common")]
    [ApiController]
    public class UploadDownLoadController : UploadBaseController
    {
        public IMapper _mapper { get; set; }
        public IUserInfo _userInfo { get; set; }
        private readonly IMediator _mediator;

        private readonly IWebHostEnvironment _hostEnvironment;



        public UploadDownLoadController(IMapper mapper, IUserInfo userInfo, IMediator mediator, IWebHostEnvironment hostEnvironment)
        {
            _hostEnvironment = hostEnvironment;
            _mediator = mediator;
            _mapper = mapper;
            _userInfo = userInfo;
        }

        /// <summary>  缩略图 </summary>
        [AllowAnonymous]
        [HttpGet("Common/LocalFilePreview")]
        public async Task<FileContentResult> LocalFilePreview(string relativePath)
        {

            var _fileStorePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, relativePath);

            var storePreviewPath = _fileStorePath + ".preview.jpeg";

            if (!System.IO.File.Exists(storePreviewPath))
            {
                ImageHelper.ResizeSave(_fileStorePath, storePreviewPath);
            }

            return new FileContentResult(await System.IO.File.ReadAllBytesAsync(storePreviewPath), "image/jpeg");

        }


        /// <summary>  通用文件下载 </summary>
        [AllowAnonymous]
        [HttpGet("CommonDocument/DownloadCommonDoc")]
        public async Task<IActionResult> DownloadCommonFile(string code, [FromServices] IRepository<CommonDocument> _commonDocumentRepository)
        {
            var (filePath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);

            new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType);

            return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName);

        }


        /// <summary>
        ///上传项目签名文档
        /// </summary>
        /// <param name="trialId"></param>
        /// <returns></returns>
        [HttpPost("TrialDocument/UploadTrialDoc/{trialId:guid}")]
        [DisableRequestSizeLimit]
        [DisableFormValueModelBinding]
        public async Task<IResponseOutput> UploadTrialDoc(Guid trialId)
        {

            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetTrialSignDocPath(_hostEnvironment, trialId, fileName));

        }

        /// <summary>
        /// 上传系统签名文档
        /// </summary>
        /// <returns></returns>
        [HttpPost("TrialDocument/UploadSystemDoc")]
        [DisableRequestSizeLimit]
        [DisableFormValueModelBinding]
        public async Task<IResponseOutput> UploadSysTemDoc()
        {

            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemSignDocPath(_hostEnvironment, fileName));

        }


        /// <summary>
        /// 上传通用文档  比如一致性核查的 比如导出的excel 模板
        /// </summary>
        /// <returns></returns>
        [HttpPost("CommonDocument/UploadCommonDoc")]
        [DisableRequestSizeLimit]
        [DisableFormValueModelBinding]
        public async Task<IResponseOutput> UploadCommonDoc()
        {

            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetCommonDocPath(_hostEnvironment, fileName));
        }


        /// <summary>
        /// 上传系统通知文档
        /// </summary>
        /// <returns></returns>
        [HttpPost("SystemNotice/UploadSystemNoticeDoc")]
        [DisableRequestSizeLimit]
        [DisableFormValueModelBinding]
        public async Task<IResponseOutput> UploadSystemNoticeDoc()
        {

            return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemNoticePath(_hostEnvironment, fileName));

        }

    }
    #endregion

}