using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Finance;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Finance;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Finance;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Microsoft.EntityFrameworkCore;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Drawing;

namespace Ladaer.BackEnd.Infrastructures.Services.Finance
{
    /// <summary>
    /// Interface cho dịch vụ xuất Excel thông tin đơn hàng
    /// </summary>
    public interface IExportOrderService
    {
        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderId hoặc OrderCode
        /// </summary>
        /// <param name="model">Thông tin đầu vào</param>
        /// <returns>Kết quả xuất file</returns>
        Task<ExportOrderResult> ExportOrdersToExcelAsync(ExportOrderModel model);

        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderId
        /// </summary>
        /// <param name="orderIds">Danh sách ID đơn hàng</param>
        /// <param name="filePath">Đường dẫn file Excel</param>
        /// <returns>Kết quả xuất file</returns>
        Task<ExportOrderResult> ExportOrdersByIdsAsync(List<int> orderIds, string filePath);

        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderCode
        /// </summary>
        /// <param name="orderCodes">Danh sách mã đơn hàng</param>
        /// <param name="filePath">Đường dẫn file Excel</param>
        /// <returns>Kết quả xuất file</returns>
        Task<ExportOrderResult> ExportOrdersByCodesAsync(List<string> orderCodes, string filePath);
    }

    /// <summary>
    /// Dịch vụ xuất Excel thông tin đơn hàng
    /// </summary>
    public class ExportOrderService : IExportOrderService
    {
        private readonly IRepository<Order> _orderRepository;
        private readonly IRepository<OrderAddress> _orderAddressRepository;
        private readonly IRepository<OrderPackage> _orderPackageRepository;
        private readonly IUserService _userService;

        public ExportOrderService(
            IRepository<Order> orderRepository,
            IRepository<OrderAddress> orderAddressRepository,
            IRepository<OrderPackage> orderPackageRepository,
            IUserService userService)
        {
            _orderRepository = orderRepository;
            _orderAddressRepository = orderAddressRepository;
            _orderPackageRepository = orderPackageRepository;
            _userService = userService;
        }

        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderId hoặc OrderCode
        /// </summary>
        /// <param name="model">Thông tin đầu vào</param>
        /// <returns>Kết quả xuất file</returns>
        public async Task<ExportOrderResult> ExportOrdersToExcelAsync(ExportOrderModel model)
        {
            var result = new ExportOrderResult();

            try
            {
                // Xác định đường dẫn file
                var fileName = string.IsNullOrEmpty(model.FileName)
                    ? $"DanhSachDonHang_{DateTime.Now:yyyyMMdd_HHmmss}"
                    : model.FileName;

                var folderPath = string.IsNullOrEmpty(model.FolderPath)
                    ? Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports")
                    : model.FolderPath;

                if (!Directory.Exists(folderPath))
                {
                    Directory.CreateDirectory(folderPath);
                }

                var filePath = Path.Combine(folderPath, $"{fileName}.xlsx");

                // Xuất theo OrderIds hoặc OrderCodes
                if (model.OrderIds != null && model.OrderIds.Any())
                {
                    result = await ExportOrdersByIdsAsync(model.OrderIds, filePath);
                }
                else if (model.OrderCodes != null && model.OrderCodes.Any())
                {
                    result = await ExportOrdersByCodesAsync(model.OrderCodes, filePath);
                }
                else
                {
                    result.Result = Result.Failed;
                    result.Message = "Vui lòng cung cấp danh sách OrderId hoặc OrderCode";
                    return result;
                }

                result.FileName = $"{fileName}.xlsx";
                result.FilePath = filePath;
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderId
        /// </summary>
        /// <param name="orderIds">Danh sách ID đơn hàng</param>
        /// <param name="filePath">Đường dẫn file Excel</param>
        /// <returns>Kết quả xuất file</returns>
        public async Task<ExportOrderResult> ExportOrdersByIdsAsync(List<int> orderIds, string filePath)
        {
            var result = new ExportOrderResult();

            try
            {
                // Query đơn hàng với tất cả thông tin liên quan
                var orders = await _orderRepository.Query()
                    .Where(o => orderIds.Contains(o.Id))
                    .Include(o => o.Customer)
                    .Include(o => o.OrderFin)
                    .Include(o => o.OrderOps)
                    .Include(o => o.OrderTimeTrack)
                    .Include(o => o.Addresses)
                    .Include(o => o.Packages)
                    .ToListAsync();

                result = await ProcessOrdersAndCreateExcel(orders, orderIds.Select(id => id.ToString()).ToList(), filePath);
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Xuất Excel thông tin đơn hàng theo danh sách OrderCode
        /// </summary>
        /// <param name="orderCodes">Danh sách mã đơn hàng</param>
        /// <param name="filePath">Đường dẫn file Excel</param>
        /// <returns>Kết quả xuất file</returns>
        public async Task<ExportOrderResult> ExportOrdersByCodesAsync(List<string> orderCodes, string filePath)
        {
            var result = new ExportOrderResult();

            try
            {
                // Query đơn hàng với tất cả thông tin liên quan
                var orders = await _orderRepository.Query()
                    .Where(o => orderCodes.Contains(o.Code))
                    .Include(o => o.Customer)
                    .Include(o => o.OrderFin)
                    .Include(o => o.OrderOps)
                    .Include(o => o.OrderTimeTrack)
                    .Include(o => o.Addresses)
                    .Include(o => o.Packages)
                    .ToListAsync();

                result = await ProcessOrdersAndCreateExcel(orders, orderCodes, filePath);
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Xử lý danh sách đơn hàng và tạo file Excel
        /// </summary>
        /// <param name="orders">Danh sách đơn hàng</param>
        /// <param name="requestedItems">Danh sách ID/Code được yêu cầu</param>
        /// <param name="filePath">Đường dẫn file</param>
        /// <returns>Kết quả xuất file</returns>
        private async Task<ExportOrderResult> ProcessOrdersAndCreateExcel(List<Order> orders, List<string> requestedItems, string filePath)
        {
            var result = new ExportOrderResult();

            // Chuyển đổi sang DTO bằng AutoMapper
            var exportItems = new List<TransferPaymentBillExportOrderItem>();

            foreach (var order in orders)
            {
                var exportItem = order.MapTo<Order, TransferPaymentBillExportOrderItem>();

                // Bổ sung thông tin địa chỉ
                var sourceAddress = order.Addresses?.FirstOrDefault(a => a.AddressType == Lada.Framework.Data.Enums.AddressType.Source);
                var destAddress = order.Addresses?.FirstOrDefault(a => a.AddressType == Lada.Framework.Data.Enums.AddressType.Dest);

                if (sourceAddress != null)
                {
                    exportItem.SenderName = sourceAddress.Name ?? "";
                    exportItem.SenderAddress = sourceAddress.Address1 ?? "";
                    exportItem.SenderPhone = sourceAddress.PhoneNumber1 ?? "";
                }

                if (destAddress != null)
                {
                    exportItem.ReceiverName = destAddress.Name ?? "";
                    exportItem.ReceiverAddress = destAddress.Address1 ?? "";
                    exportItem.ReceiverPhone = destAddress.PhoneNumber1 ?? "";
                }

                // Bổ sung thông tin hàng hóa
                if (order.Packages != null && order.Packages.Any())
                {
                    exportItem.TotalPackages = order.Packages.Count();
                    exportItem.TotalWeight = order.Packages.Sum(p => p.Weight);
                    exportItem.PackageContent = string.Join("; ", order.Packages.Select(p => p.Name).Where(c => !string.IsNullOrEmpty(c)));
                }

                exportItems.Add(exportItem);
            }

            // Tạo file Excel
            await CreateExcelFile(exportItems, filePath);

            // Tính toán kết quả
            var foundOrderCodes = orders.Select(o => o.Code).ToList();
            var notFoundItems = requestedItems.Where(item => !foundOrderCodes.Contains(item)).ToList();

            result.Result = Result.Success;
            result.Message = "Xuất file Excel thành công";
            result.FilePath = filePath;
            result.TotalOrders = orders.Count;
            result.NotFoundOrders = notFoundItems.Count;
            result.NotFoundOrderCodes = notFoundItems;

            if (File.Exists(filePath))
            {
                var fileInfo = new FileInfo(filePath);
                result.FileSize = fileInfo.Length;
            }

            return result;
        }

        /// <summary>
        /// Tạo file Excel từ danh sách đơn hàng
        /// </summary>
        /// <param name="exportItems">Danh sách đơn hàng cần xuất</param>
        /// <param name="filePath">Đường dẫn file</param>
        private async Task CreateExcelFile(List<TransferPaymentBillExportOrderItem> exportItems, string filePath)
        {
            var excelFile = new FileInfo(filePath);
            using (var package = new ExcelPackage(excelFile))
            {
                var worksheet = package.Workbook.Worksheets.Add("Danh sách đơn hàng");

                // Thiết lập header
                SetupExcelHeaders(worksheet);

                // Điền dữ liệu
                await FillExcelData(worksheet, exportItems);

                // Định dạng Excel
                FormatExcelWorksheet(worksheet, exportItems.Count);

                // Lưu file
                await package.SaveAsync();
            }
        }

        /// <summary>
        /// Thiết lập header cho Excel
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        private void SetupExcelHeaders(ExcelWorksheet worksheet)
        {
            var headers = new[]
            {
                "STT", "Mã đơn hàng", "Mã đối tác", "Khách hàng", "Sale",
                "Người gửi", "Địa chỉ gửi", "SĐT gửi", "Người nhận", "Địa chỉ nhận", "SĐT nhận",
                "Trạng thái", "Trạng thái vật lý", "Nội dung hàng",
                "Số kiện", "Khối lượng (kg)", "KL tính cước (kg)",
                "Cước phí", "Phí COD", "Phí lấy hàng", "Phí giao hàng", "Giảm giá", "Tổng cước",
                "Loại thanh toán", "Số tiền COD", "COD bao gồm cước", "Trạng thái COD",
                "TransferFee", "Trạng thái TF", "Cước nguồn", "Trạng thái CN", "Cước đích", "Trạng thái CĐ",
                "Số tiền đối soát", "Thời gian tạo", "Thời gian lấy hàng", "Thời gian giao hàng", "Ghi chú"
            };

            for (int i = 0; i < headers.Length; i++)
            {
                worksheet.Cells[1, i + 1].Value = headers[i];
            }

            // Định dạng header
            using (var range = worksheet.Cells[1, 1, 1, headers.Length])
            {
                range.Style.Font.Bold = true;
                range.Style.Font.Name = "Times New Roman";
                range.Style.Font.Size = 11;
                range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                range.Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
                range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                range.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                range.Style.Border.BorderAround(ExcelBorderStyle.Thin);
            }
        }

        /// <summary>
        /// Điền dữ liệu vào Excel
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="exportItems">Danh sách đơn hàng</param>
        private async Task FillExcelData(ExcelWorksheet worksheet, List<TransferPaymentBillExportOrderItem> exportItems)
        {
            // Lấy thông tin Sale nếu cần
            var saleIds = exportItems.Where(x => x.SaleId > 0).Select(x => x.SaleId).Distinct().ToList();
            var saleUsers = new Dictionary<int, string>();

            if (saleIds.Any())
            {
                var saleItems = await _userService.GetByListIdAsync(saleIds);
                saleUsers = saleItems.ToDictionary(s => s.Id, s => s.FullName ?? s.UserName);
            }

            int row = 2;
            int stt = 1;

            foreach (var item in exportItems)
            {
                var saleName = saleUsers.ContainsKey(item.SaleId) ? saleUsers[item.SaleId] : "";

                worksheet.Cells[row, 1].Value = stt;
                worksheet.Cells[row, 2].Value = item.OrderCode;
                worksheet.Cells[row, 3].Value = item.PartnerCode;
                worksheet.Cells[row, 4].Value = item.CustomerName;
                worksheet.Cells[row, 5].Value = saleName;

                worksheet.Cells[row, 6].Value = item.SenderName;
                worksheet.Cells[row, 7].Value = item.SenderAddress;
                worksheet.Cells[row, 8].Value = item.SenderPhone;
                worksheet.Cells[row, 9].Value = item.ReceiverName;
                worksheet.Cells[row, 10].Value = item.ReceiverAddress;
                worksheet.Cells[row, 11].Value = item.ReceiverPhone;

                worksheet.Cells[row, 12].Value = item.OrderStatus;
                worksheet.Cells[row, 13].Value = item.OrderPhysicalStatus;
                worksheet.Cells[row, 14].Value = item.PackageContent;

                worksheet.Cells[row, 15].Value = item.TotalPackages;
                worksheet.Cells[row, 16].Value = item.TotalWeightKg;
                worksheet.Cells[row, 17].Value = item.ChargeWeightKg;

                worksheet.Cells[row, 18].Value = item.Fee;
                worksheet.Cells[row, 19].Value = item.CodFee;
                worksheet.Cells[row, 20].Value = item.PickupSubFee;
                worksheet.Cells[row, 21].Value = item.DeliverySubFee;
                worksheet.Cells[row, 22].Value = item.Discount;
                worksheet.Cells[row, 23].Value = item.TotalFee;

                worksheet.Cells[row, 24].Value = item.PayFeeType;
                worksheet.Cells[row, 25].Value = item.CollectAmount;
                worksheet.Cells[row, 26].Value = item.CodIncludeFee ? "Có" : "Không";
                worksheet.Cells[row, 27].Value = item.CodStage;

                worksheet.Cells[row, 28].Value = item.TransferFeeAmount;
                worksheet.Cells[row, 29].Value = item.TransferFeeStage;
                worksheet.Cells[row, 30].Value = item.SourceFee;
                worksheet.Cells[row, 31].Value = item.SourceFeeStage;
                worksheet.Cells[row, 32].Value = item.DestFee;
                worksheet.Cells[row, 33].Value = item.DestFeeStage;

                worksheet.Cells[row, 34].Value = item.ReconciliationAmount;
                worksheet.Cells[row, 35].Value = item.OrderCreatedTimeFormatted;
                worksheet.Cells[row, 36].Value = item.PickupTimeFormatted;
                worksheet.Cells[row, 37].Value = item.DeliveryTimeFormatted;
                worksheet.Cells[row, 38].Value = item.Note;

                row++;
                stt++;
            }
        }

        /// <summary>
        /// Định dạng Excel worksheet
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="dataRowCount">Số dòng dữ liệu</param>
        private void FormatExcelWorksheet(ExcelWorksheet worksheet, int dataRowCount)
        {
            var totalRows = dataRowCount + 1; // +1 cho header
            var totalCols = 38; // Tổng số cột

            // Định dạng dữ liệu
            using (var range = worksheet.Cells[2, 1, totalRows, totalCols])
            {
                range.Style.Font.Name = "Times New Roman";
                range.Style.Font.Size = 10;
                range.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                range.Style.Border.BorderAround(ExcelBorderStyle.Thin);
            }

            // Định dạng số cho các cột tiền tệ
            var currencyColumns = new[] { 18, 19, 20, 21, 22, 23, 25, 28, 30, 32, 34 }; // Các cột chứa tiền
            foreach (var col in currencyColumns)
            {
                using (var range = worksheet.Cells[2, col, totalRows, col])
                {
                    range.Style.Numberformat.Format = "#,##0";
                    range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
                }
            }

            // Định dạng số cho các cột khối lượng
            var weightColumns = new[] { 16, 17 }; // Cột khối lượng
            foreach (var col in weightColumns)
            {
                using (var range = worksheet.Cells[2, col, totalRows, col])
                {
                    range.Style.Numberformat.Format = "#,##0.00";
                    range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
                }
            }

            // Auto-fit columns
            worksheet.Cells.AutoFitColumns();

            // Đặt chiều rộng tối thiểu cho một số cột
            worksheet.Column(2).Width = 15; // Mã đơn hàng
            worksheet.Column(7).Width = 30; // Địa chỉ gửi
            worksheet.Column(10).Width = 30; // Địa chỉ nhận
            worksheet.Column(14).Width = 25; // Nội dung hàng
        }
    }
}
