using Myshipping.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Linq;
using System.Threading.Tasks;
using Myshipping.Application.Entity;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Furion;
using Myshipping.Application.ConfigOption;
using System.IO;
using Yitter.IdGenerator;
using Furion.FriendlyException;
using Furion.RemoteRequest.Extensions;
using System.Text;
using System.Web;
using Myshipping.Application.Enum;
using System.Collections.Generic;
using Myshipping.Application.Service.BookingPrintTemplate.Dto;
using Myshipping.Core.Entity;
using Myshipping.Application.Service.BookingTemplate.Dto;
using Microsoft.AspNetCore.Authorization;

namespace Myshipping.Application
{
    /// <summary>
    /// 订舱打印模板服务
    /// </summary>
    [ApiDescriptionSettings("Application", Name = "BookingPrintTemplate", Order = 1)]
    public class BookingPrintTemplateService : IBookingPrintTemplateService, IDynamicApiController, ITransient
    {
        private readonly SqlSugarRepository<BookingPrintTemplate> _rep;
        private readonly SqlSugarRepository<BookingPrinttemplateRight> _repRight;
        private readonly SqlSugarRepository<SysUser> _repUser;
        private readonly ILogger<BookingPrintTemplate> _logger;
        private readonly SqlSugarRepository<BookingExcelTemplate> _excelrep;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public BookingPrintTemplateService(SqlSugarRepository<BookingPrintTemplate> rep,
            SqlSugarRepository<BookingPrinttemplateRight> repRight,
            SqlSugarRepository<SysUser> repUser,
            SqlSugarRepository<BookingExcelTemplate> excelrep,
            ILogger<BookingPrintTemplate> logger,
            IHttpContextAccessor httpContextAccessor)
        {
            _rep = rep;
            _repRight = repRight;
            _repUser = repUser;
            _logger = logger;
            _excelrep = excelrep;
            _httpContextAccessor = httpContextAccessor;
        }

        /// <summary>
        /// 分页查询订舱打印模板
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/page")]
        public async Task<dynamic> Page([FromQuery] QueryBookingPrintTemplateInput input)
        {
            var entities = await _rep.AsQueryable().Filter(null, true)
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.TypeName), u => u.TypeName.Contains(input.TypeName.Trim()))
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.TenantName), u => u.TenantName.Contains(input.TenantName.Trim()))
                                     .WhereIF(input.IsMain.HasValue, u => u.IsMain == input.IsMain)
                                     .WhereIF(input.IsSub.HasValue, u => u.IsSub == input.IsSub)
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.DisplayName), u => u.DisplayName.Contains(input.DisplayName.Trim()))
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.CateCode), u => u.CateCode.Contains(input.CateCode.Trim()))
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.CateName), u => u.CateName.Contains(input.CateName.Trim()))
                                     .WhereIF(!string.IsNullOrWhiteSpace(input.Type), u => u.Type == input.Type)
                                     .ToPagedListAsync(input.PageNo, input.PageSize);
            return entities.XnPagedResult();
        }
        /// <summary>
        /// 赋权列表
        /// </summary>
        /// <param name="KeyWord"></param>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/GetPrintTemplateList")]
        public async Task<dynamic> GetPrintTemplateList(string KeyWord)
        {
            return await _rep.AsQueryable().Where(x => x.TenantId == UserManager.TENANT_ID).WhereIF(!string.IsNullOrWhiteSpace(KeyWord), x => x.FileName.StartsWith(KeyWord))
                                      .ToListAsync();

        }


        /// <summary>
        /// 增加订舱打印模板(准备作废,使用Save代替)
        /// </summary>
        /// <param name="file">模板文件</param>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/BookingPrintTemplate/add")]
        public async Task Add(IFormFile file, [FromForm] AddBookingPrintTemplateInput input)
        {
            //未上传打印模板文件
            if (file == null || file.Length == 0)
            {
                throw Oops.Bah(BookingErrorCode.BOOK113);
            }

            var opt = App.GetOptions<PrintTemplateOptions>();
            var originalFilename = file.FileName; // 文件原始名称
            var fileSuffix = Path.GetExtension(file.FileName).ToLower(); // 文件后缀
            if (!opt.fileType.Contains(fileSuffix))
            {
                throw Oops.Bah(BookingErrorCode.BOOK114);
            }

            var cc = _rep.AsQueryable().Filter(null, true).Count(c => c.TenantId == input.TenantId && c.TypeCode == input.TypeCode);
            if (cc > 0)
            {
                throw Oops.Bah($"{input.TenantName} 已存在 {input.TypeName} 类型的打印模板");
            }

            var dirAbs = string.Empty;
            if (string.IsNullOrEmpty(opt.basePath))
            {
                dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath);
            }
            else
            {

                dirAbs = Path.Combine(opt.basePath, opt.relativePath);
            }

            if (!Directory.Exists(dirAbs))
                Directory.CreateDirectory(dirAbs);


            // 先存库获取Id
            var id = YitIdHelper.NextId();
            var fileSaveName = $"{id}{fileSuffix}".ToLower();
            var fileRelaPath = Path.Combine(opt.relativePath, fileSaveName).ToLower();
            var fileAbsPath = Path.Combine(dirAbs, fileSaveName).ToLower();
            var newFile = new BookingPrintTemplate
            {
                Id = id,
                FileName = originalFilename,
                FilePath = fileRelaPath,
                TypeCode = input.TypeCode,
                TypeName = input.TypeName,
                TenantId = input.TenantId,
                TenantName = input.TenantName,
                IsMain = input.IsMain.HasValue && input.IsMain.Value ? true : false,
                IsSub = input.IsSub.HasValue && input.IsSub.Value ? true : false,
            };
            await _rep.InsertAsync(newFile);
            using (var stream = File.Create(fileAbsPath))
            {
                await file.CopyToAsync(stream);
            }

        }


        /// <summary>
        /// 更新订舱打印模板(准备作废,使用Save代替)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/BookingPrintTemplate/edit")]
        public async Task Update(IFormFile file, [FromForm] UpdateBookingPrintTemplateInput input)
        {
            var cc = _rep.AsQueryable().Filter(null, true).Count(c => c.TenantId == input.TenantId && c.TypeCode == input.TypeCode && c.Id != input.Id);
            if (cc > 0)
            {
                throw Oops.Bah($"{input.TenantName} 已存在 {input.TypeName} 类型的打印模板");
            }

            var entity = _rep.AsQueryable().Filter(null, true).First(x => x.Id == input.Id);
            if (entity == null)
            {
                throw Oops.Bah(BookingErrorCode.BOOK112);
            }

            entity = input.Adapt(entity);

            if (file != null)
            {
                var opt = App.GetOptions<PrintTemplateOptions>();
                var originalFilename = file.FileName; // 文件原始名称
                var fileSuffix = Path.GetExtension(file.FileName).ToLower(); // 文件后缀  
                if (!opt.fileType.Contains(fileSuffix))
                {
                    throw Oops.Bah(BookingErrorCode.BOOK114);
                }

                var dirAbs = string.Empty;
                if (string.IsNullOrEmpty(opt.basePath))
                {
                    dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath);
                }
                else
                {
                    dirAbs = Path.Combine(opt.basePath, opt.relativePath);
                }

                if (!Directory.Exists(dirAbs))
                    Directory.CreateDirectory(dirAbs);

                // 先存库获取Id
                var fileSaveName = $"{entity.Id}{fileSuffix}".ToLower();
                var fileRelaPath = Path.Combine(opt.relativePath, fileSaveName).ToLower();
                var fileAbsPath = Path.Combine(dirAbs, fileSaveName).ToLower();

                entity.FileName = originalFilename;
                entity.FilePath = fileRelaPath;

                using (var stream = File.Create(fileAbsPath))
                {
                    await file.CopyToAsync(stream);
                }
            }

            await _rep.UpdateAsync(entity);
        }

        /// <summary>
        /// 保存订舱打印模板(新增或修改)
        /// </summary>
        /// <param name="file"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/BookingPrintTemplate/save")]
        public async Task<long> Save(IFormFile file, [FromForm] SaveBookingPrintTemplateInput input)
        {
            var opt = App.GetOptions<PrintTemplateOptions>();
            if (file != null && file.Length > 0)
            {
                var fileSuffix = Path.GetExtension(file.FileName).ToLower(); // 文件后缀
                if (!opt.fileType.Contains(fileSuffix))
                {
                    throw Oops.Bah(BookingErrorCode.BOOK114);
                }
            }

            BookingPrintTemplate entity = null;
            if (input.Id > 0)
            {
                entity = _rep.AsQueryable().Filter(null, true).First(x => x.Id == input.Id);
                input.Adapt(entity);
                await _rep.UpdateAsync(entity);
            }
            else
            {
                //新增时必须上传文件
                if (file == null || file.Length == 0)
                {
                    throw Oops.Bah(BookingErrorCode.BOOK113);
                }

                entity = input.Adapt<BookingPrintTemplate>();
                await _rep.InsertAsync(entity);
            }

            if (file != null && file.Length > 0)
            {
                var originalFilename = file.FileName; // 文件原始名称

                var dirAbs = string.Empty;
                if (string.IsNullOrEmpty(opt.basePath))
                {
                    dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath);
                }
                else
                {
                    dirAbs = Path.Combine(opt.basePath, opt.relativePath);
                }

                if (!Directory.Exists(dirAbs))
                    Directory.CreateDirectory(dirAbs);


                // 先存库获取Id
                var id = YitIdHelper.NextId();
                var fileSuffix = Path.GetExtension(file.FileName).ToLower();
                var fileSaveName = $"{id}{fileSuffix}".ToLower();
                var fileRelaPath = Path.Combine(opt.relativePath, fileSaveName).ToLower();
                var fileAbsPath = Path.Combine(dirAbs, fileSaveName).ToLower();
                using (var stream = File.Create(fileAbsPath))
                {
                    await file.CopyToAsync(stream);
                }

                entity.FileName = originalFilename;
                entity.FilePath = fileRelaPath;
                await _rep.UpdateAsync(entity);
            }

            return entity.Id;
        }

        /// <summary>
        /// 删除订舱打印模板
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/BookingPrintTemplate/delete")]
        public async Task Delete(GetBookingPrintTemplateInput input)
        {
            _rep.Context.QueryFilter.Clear();
            var entity = await _rep.FirstOrDefaultAsync(u => u.Id == input.Id);
            await _rep.DeleteAsync(entity);
        }

        /// <summary>
        /// 获取订舱打印模板
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/detail")]
        public async Task<BookingPrintTemplate> Get([FromQuery] GetBookingPrintTemplateInput input)
        {
            return await _rep.FirstOrDefaultAsync(u => u.Id == input.Id);
        }

        ///// <summary>
        ///// 获取订舱打印模板列表
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //[HttpGet("/BookingPrintTemplate/list")]
        //public async Task<dynamic> List([FromQuery] QueryBookingPrintTemplateInput input)
        //{
        //    return await _rep.ToListAsync();
        //}

        /// <summary>
        /// 下载模板文件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/download"), AllowAnonymous]
        public async Task<IActionResult> Download(long id)
        {
            var printFile = await _rep.AsQueryable().Filter(null, true).FirstAsync(u => u.Id == id);
            if (printFile == null)
            {
                throw Oops.Bah(BookingErrorCode.BOOK115);
            }


            var opt = App.GetOptions<PrintTemplateOptions>();
            var dirAbs = opt.basePath;
            if (string.IsNullOrEmpty(dirAbs))
            {
                dirAbs = App.WebHostEnvironment.WebRootPath;
            }

            var fileFullPath = Path.Combine(dirAbs, printFile.FilePath);
            if (!File.Exists(fileFullPath))
            {
                throw Oops.Bah(BookingErrorCode.BOOK115);
            }

            var result = new FileStreamResult(new FileStream(fileFullPath, FileMode.Open), "application/octet-stream") { FileDownloadName = printFile.FileName };
            return result;
        }
        /// <summary>
        /// 新增打印模板权限
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SqlSugarUnitOfWork]
        [HttpPost("/BookingPrintTemplate/AddPrinttemplateRight")]
        public async Task AddPrinttemplateRight(BookingPrinttemplateRightDto input)
        {
            if (input == null)
            {

                throw Oops.Bah("未上传正确数据");
            }

            //新版支持批量
            if (input.UserIdList == null)
            {
                input.UserIdList = new List<long>();
            }

            //兼容老版单个设置
            if (input.SysUserId > 0 && !input.UserIdList.Contains(input.SysUserId))
            {
                input.UserIdList.Add(input.SysUserId);
            }

            foreach (var item in input.PrintTemplateId)
            {
                foreach (var uid in input.UserIdList)
                {
                    var ent = _repRight.FirstOrDefault(x => x.SysUserId == uid && x.PrintTemplateId == item);
                    if (ent == null)
                    {
                        BookingPrinttemplateRight right = new BookingPrinttemplateRight();
                        right.SysUserId = uid;
                        right.PrintTemplateId = item;
                        await _repRight.InsertAsync(right);
                    }
                }
            }
        }
        /// <summary>
        /// 获取打印模板权限
        /// </summary>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/GetPrinttemplateRightList")]
        public async Task<dynamic> GetPrinttemplateRightList(long userId, string cateCode, string type, string displayName)
        {
            var userlist = await _repUser.AsQueryable().Filter(null, true).ToListAsync();
            var list = await _repRight.AsQueryable().InnerJoin<BookingPrintTemplate>((d, t) => d.PrintTemplateId == t.Id && t.TenantId == UserManager.TENANT_ID).
                WhereIF(userId != 0, d => d.SysUserId == userId).
                  WhereIF(!string.IsNullOrWhiteSpace(displayName), (d, t) => t.DisplayName.Contains(displayName)).
                  WhereIF(!string.IsNullOrWhiteSpace(cateCode), (d, t) => t.CateCode == cateCode).
                   WhereIF(!string.IsNullOrWhiteSpace(type), (d, t) => t.Type == type).
                Select((d, t) => new BookingPrinttemplateDto
                {
                    Id = d.Id,
                    PrintTemplateId = t.Id,
                    SysUserId = d.SysUserId,
                    TypeCode = t.TypeCode,
                    TypeName = t.TypeName,
                    FilePath = t.FilePath,
                    FileName = t.FileName,
                    TenantName = t.TenantName,
                    DisplayName = t.DisplayName,
                    CateCode = t.CateCode,
                    CateName = t.CateName,
                    Type = t.Type,
                    UserName = "",
                }).ToListAsync();


            foreach (var item in list)
            {
                var username = userlist.Where(x => x.Id == item.SysUserId).Select(x => x.Name).FirstOrDefault();
                item.UserName = username;
            }
            return list;
        }

        /// <summary>
        /// 删除打印模板权限
        /// </summary>
        /// <param name="Ids"></param>
        /// <returns></returns>
        [HttpGet("/BookingPrintTemplate/DeletePrinttemplateRight")]
        public async Task DeletePrinttemplateRight([FromQuery] List<long> Ids)
        {

            await _repRight.DeleteAsync(x => Ids.Contains(x.Id));
        }


        /// <summary>
        /// 新增编辑excel模板
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("/BookingTemplate/AddOrUpdateExcelTemplate")]
        public async Task AddOrUpdateExcelTemplate(BookingExcelTemplateDto dto)
        {
            await _excelrep.DeleteAsync(x => x.PId == dto.Pid);
            var list = new List<BookingExcelTemplate>();
            foreach (var item in dto.children)
            {
                var entity = item.Adapt<BookingExcelTemplate>();
                entity.PId = dto.Pid;
                entity.Id = 0;
                list.Add(entity);
            }
            await _excelrep.InsertAsync(list);
        }
        /// <summary>
        /// 获取excel模板详情
        /// </summary>
        /// <param name="Id">模板ID</param>
        /// <returns></returns>
        [HttpGet("/BookingTemplate/BookingExcelTemplateList")]
        public async Task<dynamic> BookingExcelTemplateList(long Id)
        {
            return await _excelrep.AsQueryable().Where(x => x.PId == Id).OrderBy(x => x.Id).ToListAsync();
        }

    }
}