using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.DTO;
using OfficeOpenXml;

namespace Ladaer.BackEnd.Infrastructures.Services.Orders.Exports
{
    /// <summary>
    /// Interface cho template xuất Excel đơn hàng
    /// </summary>
    /// <typeparam name="TExportItem">Loại DTO export</typeparam>
    public interface IOrderExportTemplate<TExportItem> where TExportItem : class
    {
        /// <summary>
        /// Tên template
        /// </summary>
        string TemplateName { get; }

        /// <summary>
        /// Mô tả template
        /// </summary>
        string Description { get; }

        /// <summary>
        /// Tên worksheet mặc định
        /// </summary>
        string DefaultWorksheetName { get; }

        /// <summary>
        /// Chuyển đổi danh sách Order thành danh sách DTO export
        /// </summary>
        /// <param name="orders">Danh sách đơn hàng</param>
        /// <returns>Danh sách DTO export</returns>
        Task<List<TExportItem>> ConvertOrdersToExportItemsAsync(List<Order> orders);

        /// <summary>
        /// Thiết lập header cho Excel
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        void SetupHeaders(ExcelWorksheet worksheet);

        /// <summary>
        /// Điền dữ liệu vào Excel
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="exportItems">Danh sách DTO export</param>
        /// <returns>Task</returns>
        Task FillDataAsync(ExcelWorksheet worksheet, List<TExportItem> exportItems);

        /// <summary>
        /// Định dạng Excel worksheet
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="dataRowCount">Số dòng dữ liệu</param>
        void FormatWorksheet(ExcelWorksheet worksheet, int dataRowCount);

        /// <summary>
        /// Validate dữ liệu trước khi xuất
        /// </summary>
        /// <param name="orders">Danh sách đơn hàng</param>
        /// <returns>Kết quả validation</returns>
        Task<BaseResult> ValidateDataAsync(List<Order> orders);

        /// <summary>
        /// Lấy tên file mặc định
        /// </summary>
        /// <param name="prefix">Prefix tên file</param>
        /// <returns>Tên file</returns>
        string GetDefaultFileName(string? prefix = null);
    }

    /// <summary>
    /// Abstract base class cho Order Export Template
    /// </summary>
    /// <typeparam name="TExportItem">Loại DTO export</typeparam>
    public abstract class BaseOrderExportTemplate<TExportItem> : IOrderExportTemplate<TExportItem>
        where TExportItem : class
    {
        public abstract string TemplateName { get; }
        public abstract string Description { get; }
        public abstract string DefaultWorksheetName { get; }

        public abstract Task<List<TExportItem>> ConvertOrdersToExportItemsAsync(List<Order> orders);
        public abstract void SetupHeaders(ExcelWorksheet worksheet);
        public abstract Task FillDataAsync(ExcelWorksheet worksheet, List<TExportItem> exportItems);
        public abstract void FormatWorksheet(ExcelWorksheet worksheet, int dataRowCount);

        /// <summary>
        /// Validation mặc định - có thể override
        /// </summary>
        /// <param name="orders">Danh sách đơn hàng</param>
        /// <returns>Kết quả validation</returns>
        public virtual Task<BaseResult> ValidateDataAsync(List<Order> orders)
        {
            var result = new BaseResult();

            if (orders == null || !orders.Any())
            {
                result.Result = Result.Failed;
                result.Message = "Không có đơn hàng nào để xuất";
                return Task.FromResult(result);
            }

            result.Result = Result.Success;
            return Task.FromResult(result);
        }

        /// <summary>
        /// Tạo tên file mặc định
        /// </summary>
        /// <param name="prefix">Prefix tên file</param>
        /// <returns>Tên file</returns>
        public virtual string GetDefaultFileName(string? prefix = null)
        {
            var filePrefix = string.IsNullOrEmpty(prefix) ? TemplateName : prefix;
            return $"{filePrefix}_{DateTime.Now:yyyyMMdd_HHmmss}";
        }

        /// <summary>
        /// Thiết lập style chung cho header
        /// </summary>
        /// <param name="headerRange">Range header</param>
        protected virtual void SetupHeaderStyle(ExcelRange headerRange)
        {
            headerRange.Style.Font.Bold = true;
            headerRange.Style.Font.Name = "Times New Roman";
            headerRange.Style.Font.Size = 11;
            headerRange.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
            headerRange.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightBlue);
            headerRange.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
            headerRange.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
            headerRange.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
        }

        /// <summary>
        /// Thiết lập style chung cho dữ liệu
        /// </summary>
        /// <param name="dataRange">Range dữ liệu</param>
        protected virtual void SetupDataStyle(ExcelRange dataRange)
        {
            dataRange.Style.Font.Name = "Times New Roman";
            dataRange.Style.Font.Size = 10;
            dataRange.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
            dataRange.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
        }

        /// <summary>
        /// Định dạng cột tiền tệ
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="columnIndex">Index cột</param>
        /// <param name="startRow">Dòng bắt đầu</param>
        /// <param name="endRow">Dòng kết thúc</param>
        protected virtual void FormatCurrencyColumn(ExcelWorksheet worksheet, int columnIndex, int startRow, int endRow)
        {
            using (var range = worksheet.Cells[startRow, columnIndex, endRow, columnIndex])
            {
                range.Style.Numberformat.Format = "#,##0";
                range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
            }
        }

        /// <summary>
        /// Định dạng cột số thập phân
        /// </summary>
        /// <param name="worksheet">Worksheet</param>
        /// <param name="columnIndex">Index cột</param>
        /// <param name="startRow">Dòng bắt đầu</param>
        /// <param name="endRow">Dòng kết thúc</param>
        /// <param name="decimalPlaces">Số chữ số thập phân</param>
        protected virtual void FormatDecimalColumn(ExcelWorksheet worksheet, int columnIndex, int startRow, int endRow, int decimalPlaces = 2)
        {
            using (var range = worksheet.Cells[startRow, columnIndex, endRow, columnIndex])
            {
                var format = decimalPlaces == 0 ? "#,##0" : $"#,##0.{new string('0', decimalPlaces)}";
                range.Style.Numberformat.Format = format;
                range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
            }
        }
    }
}
