using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Finance;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Orders;
using Ladaer.BackEnd.Infrastructures.Services.Orders.Exports.Templates;
using Microsoft.EntityFrameworkCore;
using OfficeOpenXml;
using System.Diagnostics;

namespace Ladaer.BackEnd.Infrastructures.Services.Orders.Exports
{
    /// <summary>
    /// Interface cho dịch vụ xuất Excel đơn hàng (Generic)
    /// </summary>
    public interface IOrderExportService
    {
        /// <summary>
        /// Xuất Excel đơn hàng với template được chỉ định
        /// </summary>
        /// <param name="model">Model xuất Excel</param>
        /// <returns>Kết quả xuất file</returns>
        Task<OrderExportResult> ExportOrdersAsync(OrderExportModel model);

        /// <summary>
        /// Xuất Excel đơn hàng với filter nâng cao
        /// </summary>
        /// <param name="model">Model xuất Excel với filter</param>
        /// <returns>Kết quả xuất file</returns>
        Task<OrderExportResult> ExportOrdersWithFilterAsync(OrderExportWithFilterModel model);

        /// <summary>
        /// Lấy danh sách template có sẵn
        /// </summary>
        /// <returns>Danh sách template</returns>
        List<OrderExportTemplateInfo> GetAvailableTemplates();

        /// <summary>
        /// Kiểm tra template có tồn tại không
        /// </summary>
        /// <param name="templateType">Loại template</param>
        /// <returns>True nếu tồn tại</returns>
        bool IsTemplateSupported(OrderExportTemplateType templateType);
    }

    /// <summary>
    /// Dịch vụ xuất Excel đơn hàng (Generic)
    /// </summary>
    public class OrderExportService : IOrderExportService
    {
        private readonly IRepository<Order> _orderRepository;
        private readonly FinanceOrderExportTemplate _financeTemplate;
        private readonly BasicOrderExportTemplate _basicTemplate;

        public OrderExportService(
            IRepository<Order> orderRepository,
            FinanceOrderExportTemplate financeTemplate,
            BasicOrderExportTemplate basicTemplate)
        {
            _orderRepository = orderRepository;
            _financeTemplate = financeTemplate;
            _basicTemplate = basicTemplate;
        }

        /// <summary>
        /// Xuất Excel đơn hàng với template được chỉ định
        /// </summary>
        /// <param name="model">Model xuất Excel</param>
        /// <returns>Kết quả xuất file</returns>
        public async Task<OrderExportResult> ExportOrdersAsync(OrderExportModel model)
        {
            var result = new OrderExportResult
            {
                TemplateType = model.TemplateType,
                ProcessStartTime = DateTimeOffset.Now
            };

            try
            {
                // Validate model
                var validationErrors = model.Validate();
                if (validationErrors.Any())
                {
                    result.Result = Result.Failed;
                    result.Message = string.Join("; ", validationErrors);
                    return result;
                }

                // Xác định đường dẫn file
                var fileName = await GenerateFileNameAsync(model);
                var folderPath = GetFolderPath(model.FolderPath);
                var filePath = Path.Combine(folderPath, $"{fileName}.xlsx");

                // Query đơn hàng
                var stopwatch = Stopwatch.StartNew();
                var orders = await QueryOrdersAsync(model);
                result.ProcessInfo.DatabaseQueryTimeMs = stopwatch.ElapsedMilliseconds;

                // Validate dữ liệu và xuất theo template
                result = await ExportWithTemplateAsync(model.TemplateType, orders, filePath, result);

                // Tính toán kết quả
                result.FilePath = filePath;
                result.FileName = $"{fileName}.xlsx";
                result.TotalOrders = orders.Count;

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

                result.MarkProcessCompleted();
                result.Result = Result.Success;
                result.Message = "Xuất file Excel thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
                result.MarkProcessCompleted();
            }

            return result;
        }

        /// <summary>
        /// Xuất Excel đơn hàng với filter nâng cao
        /// </summary>
        /// <param name="model">Model xuất Excel với filter</param>
        /// <returns>Kết quả xuất file</returns>
        public async Task<OrderExportResult> ExportOrdersWithFilterAsync(OrderExportWithFilterModel model)
        {
            var result = new OrderExportResult
            {
                TemplateType = model.TemplateType,
                ProcessStartTime = DateTimeOffset.Now
            };

            try
            {
                // Validate model
                var validationErrors = model.Validate();
                if (validationErrors.Any())
                {
                    result.Result = Result.Failed;
                    result.Message = string.Join("; ", validationErrors);
                    return result;
                }

                // Xác định đường dẫn file
                var fileName = await GenerateFileNameAsync(model);
                var folderPath = GetFolderPath(model.FolderPath);
                var filePath = Path.Combine(folderPath, $"{fileName}.xlsx");

                // Query đơn hàng với filter
                var stopwatch = Stopwatch.StartNew();
                var orders = await QueryOrdersWithFilterAsync(model);
                result.ProcessInfo.DatabaseQueryTimeMs = stopwatch.ElapsedMilliseconds;

                // Validate dữ liệu và xuất theo template
                result = await ExportWithTemplateAsync(model.TemplateType, orders, filePath, result);

                // Tính toán kết quả
                result.FilePath = filePath;
                result.FileName = $"{fileName}.xlsx";
                result.TotalOrders = orders.Count;

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

                result.MarkProcessCompleted();
                result.Result = Result.Success;
                result.Message = "Xuất file Excel thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
                result.MarkProcessCompleted();
            }

            return result;
        }

        /// <summary>
        /// Lấy danh sách template có sẵn
        /// </summary>
        /// <returns>Danh sách template</returns>
        public List<OrderExportTemplateInfo> GetAvailableTemplates()
        {
            return new List<OrderExportTemplateInfo>
            {
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Finance,
                    Name = _financeTemplate.TemplateName,
                    Description = _financeTemplate.Description,
                    IsSupported = true
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Basic,
                    Name = _basicTemplate.TemplateName,
                    Description = _basicTemplate.Description,
                    IsSupported = true
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Operations,
                    Name = "Operations",
                    Description = "Template xuất Excel cho mục đích vận hành",
                    IsSupported = false // Chưa implement
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Logistics,
                    Name = "Logistics",
                    Description = "Template xuất Excel cho mục đích logistics",
                    IsSupported = false // Chưa implement
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Reporting,
                    Name = "Reporting",
                    Description = "Template xuất Excel cho mục đích báo cáo",
                    IsSupported = false // Chưa implement
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Customer,
                    Name = "Customer",
                    Description = "Template xuất Excel cho khách hàng",
                    IsSupported = false // Chưa implement
                },
                new OrderExportTemplateInfo
                {
                    TemplateType = OrderExportTemplateType.Full,
                    Name = "Full",
                    Description = "Template xuất Excel đầy đủ thông tin",
                    IsSupported = false // Chưa implement
                }
            };
        }

        /// <summary>
        /// Kiểm tra template có tồn tại không
        /// </summary>
        /// <param name="templateType">Loại template</param>
        /// <returns>True nếu tồn tại</returns>
        public bool IsTemplateSupported(OrderExportTemplateType templateType)
        {
            return templateType switch
            {
                OrderExportTemplateType.Finance => true,
                OrderExportTemplateType.Basic => true,
                _ => false
            };
        }

        #region Private Methods

        /// <summary>
        /// Query đơn hàng theo model cơ bản
        /// </summary>
        /// <param name="model">Model xuất Excel</param>
        /// <returns>Danh sách đơn hàng</returns>
        private async Task<List<Order>> QueryOrdersAsync(OrderExportModel model)
        {
            var baseQuery = _orderRepository.Query()
                .Include(o => o.Customer)
                .Include(o => o.OrderFin)
                .Include(o => o.OrderOps)
                .Include(o => o.OrderTimeTrack)
                .Include(o => o.Addresses)
                .Include(o => o.Packages);

            // Filter theo OrderIds hoặc OrderCodes
            if (model.OrderIds != null && model.OrderIds.Any())
            {
                return await baseQuery.Where(o => model.OrderIds.Contains(o.Id)).ToListAsync();
            }
            else if (model.OrderCodes != null && model.OrderCodes.Any())
            {
                return await baseQuery.Where(o => model.OrderCodes.Contains(o.Code)).ToListAsync();
            }

            return await baseQuery.ToListAsync();
        }

        /// <summary>
        /// Query đơn hàng với filter nâng cao
        /// </summary>
        /// <param name="model">Model xuất Excel với filter</param>
        /// <returns>Danh sách đơn hàng</returns>
        private async Task<List<Order>> QueryOrdersWithFilterAsync(OrderExportWithFilterModel model)
        {
            var baseQuery = _orderRepository.Query()
                .Include(o => o.Customer)
                .Include(o => o.OrderFin)
                .Include(o => o.OrderOps)
                .Include(o => o.OrderTimeTrack)
                .Include(o => o.Addresses)
                .Include(o => o.Packages);

            IQueryable<Order> query = baseQuery;

            // Filter theo OrderIds hoặc OrderCodes (nếu có)
            if (model.OrderIds != null && model.OrderIds.Any())
            {
                query = query.Where(o => model.OrderIds.Contains(o.Id));
            }
            else if (model.OrderCodes != null && model.OrderCodes.Any())
            {
                query = query.Where(o => model.OrderCodes.Contains(o.Code));
            }
            else
            {
                // Áp dụng các filter khác
                if (model.CustomerIds != null && model.CustomerIds.Any())
                {
                    query = query.Where(o => model.CustomerIds.Contains(o.CustomerId));
                }

                if (model.SaleIds != null && model.SaleIds.Any())
                {
                    query = query.Where(o => model.SaleIds.Contains(o.SaleId));
                }

                if (model.CreatedFromDate.HasValue)
                {
                    query = query.Where(o => o.CreatedTime >= model.CreatedFromDate.Value);
                }

                if (model.CreatedToDate.HasValue)
                {
                    query = query.Where(o => o.CreatedTime <= model.CreatedToDate.Value);
                }

                if (model.PickupFromDate.HasValue)
                {
                    query = query.Where(o => o.OrderTimeTrack != null && o.OrderTimeTrack.PickupTime >= model.PickupFromDate.Value);
                }

                if (model.PickupToDate.HasValue)
                {
                    query = query.Where(o => o.OrderTimeTrack != null && o.OrderTimeTrack.PickupTime <= model.PickupToDate.Value);
                }

                if (model.DeliveryFromDate.HasValue)
                {
                    query = query.Where(o => o.OrderTimeTrack != null && o.OrderTimeTrack.DeliveryDate >= model.DeliveryFromDate.Value);
                }

                if (model.DeliveryToDate.HasValue)
                {
                    query = query.Where(o => o.OrderTimeTrack != null && o.OrderTimeTrack.DeliveryDate <= model.DeliveryToDate.Value);
                }

                if (!string.IsNullOrWhiteSpace(model.SearchKeyword))
                {
                    var keyword = model.SearchKeyword.ToLower();
                    query = query.Where(o =>
                        o.Code.ToLower().Contains(keyword) ||
                        (o.Customer != null && o.Customer.FullName.ToLower().Contains(keyword)) ||
                        (o.Customer != null && o.Customer.PhoneNumber.Contains(keyword)));
                }
            }

            return await query.ToListAsync();
        }

        /// <summary>
        /// Xuất Excel với template được chỉ định
        /// </summary>
        /// <param name="templateType">Loại template</param>
        /// <param name="orders">Danh sách đơn hàng</param>
        /// <param name="filePath">Đường dẫn file</param>
        /// <param name="result">Kết quả xuất</param>
        /// <returns>Kết quả xuất đã cập nhật</returns>
        private async Task<OrderExportResult> ExportWithTemplateAsync(OrderExportTemplateType templateType, List<Order> orders, string filePath, OrderExportResult result)
        {
            var stopwatch = Stopwatch.StartNew();

            switch (templateType)
            {
                case OrderExportTemplateType.Finance:
                    result.TemplateName = _financeTemplate.TemplateName;

                    // Validate dữ liệu
                    var financeValidation = await _financeTemplate.ValidateDataAsync(orders);
                    if (financeValidation.Result != Result.Success)
                    {
                        result.Result = financeValidation.Result;
                        result.Message = financeValidation.Message;
                        return result;
                    }

                    // Convert và xuất
                    var financeItems = await _financeTemplate.ConvertOrdersToExportItemsAsync(orders);
                    result.ProcessInfo.DataConversionTimeMs = stopwatch.ElapsedMilliseconds;

                    stopwatch.Restart();
                    await CreateExcelFileAsync(_financeTemplate, financeItems, filePath);
                    result.ProcessInfo.ExcelGenerationTimeMs = stopwatch.ElapsedMilliseconds;
                    break;

                case OrderExportTemplateType.Basic:
                    result.TemplateName = _basicTemplate.TemplateName;

                    // Validate dữ liệu
                    var basicValidation = await _basicTemplate.ValidateDataAsync(orders);
                    if (basicValidation.Result != Result.Success)
                    {
                        result.Result = basicValidation.Result;
                        result.Message = basicValidation.Message;
                        return result;
                    }

                    // Convert và xuất
                    var basicItems = await _basicTemplate.ConvertOrdersToExportItemsAsync(orders);
                    result.ProcessInfo.DataConversionTimeMs = stopwatch.ElapsedMilliseconds;

                    stopwatch.Restart();
                    await CreateExcelFileAsync(_basicTemplate, basicItems, filePath);
                    result.ProcessInfo.ExcelGenerationTimeMs = stopwatch.ElapsedMilliseconds;
                    break;

                default:
                    result.Result = Result.Failed;
                    result.Message = $"Template {templateType} chưa được hỗ trợ";
                    return result;
            }

            return result;
        }

        /// <summary>
        /// Tạo file Excel với template
        /// </summary>
        /// <typeparam name="TExportItem">Loại DTO export</typeparam>
        /// <param name="template">Template xuất</param>
        /// <param name="exportItems">Danh sách items</param>
        /// <param name="filePath">Đường dẫn file</param>
        private async Task CreateExcelFileAsync<TExportItem>(IOrderExportTemplate<TExportItem> template, List<TExportItem> exportItems, string filePath)
            where TExportItem : class
        {
            var excelFile = new FileInfo(filePath);
            using (var package = new ExcelPackage(excelFile))
            {
                var worksheet = package.Workbook.Worksheets.Add(template.DefaultWorksheetName);

                // Thiết lập header
                template.SetupHeaders(worksheet);

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

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

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

        /// <summary>
        /// Tạo tên file
        /// </summary>
        /// <param name="model">Model xuất Excel</param>
        /// <returns>Tên file</returns>
        private async Task<string> GenerateFileNameAsync(OrderExportModel model)
        {
            if (!string.IsNullOrEmpty(model.FileName))
            {
                return model.FileName;
            }

            var template = GetTemplate(model.TemplateType);
            return template?.GetDefaultFileName() ?? $"DanhSachDonHang_{DateTime.Now:yyyyMMdd_HHmmss}";
        }

        /// <summary>
        /// Lấy đường dẫn thư mục
        /// </summary>
        /// <param name="folderPath">Đường dẫn tùy chọn</param>
        /// <returns>Đường dẫn thư mục</returns>
        private string GetFolderPath(string? folderPath)
        {
            var path = string.IsNullOrEmpty(folderPath)
                ? Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports")
                : folderPath;

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

            return path;
        }

        /// <summary>
        /// Lấy template theo loại
        /// </summary>
        /// <param name="templateType">Loại template</param>
        /// <returns>Template</returns>
        private IOrderExportTemplate<object>? GetTemplate(OrderExportTemplateType templateType)
        {
            return templateType switch
            {
                OrderExportTemplateType.Finance => _financeTemplate as IOrderExportTemplate<object>,
                OrderExportTemplateType.Basic => _basicTemplate as IOrderExportTemplate<object>,
                _ => null
            };
        }

        #endregion
    }

    /// <summary>
    /// Thông tin về template xuất Excel
    /// </summary>
    public class OrderExportTemplateInfo
    {
        public OrderExportTemplateType TemplateType { get; set; }
        public string Name { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public bool IsSupported { get; set; }
        public int EstimatedColumns { get; set; }
        public List<string> RequiredIncludes { get; set; } = new List<string>();
    }
}
