using Dapper;
using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Domains.Medias;
using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Enums;
using static Lada.Framework.Data.Enums.OrderFinEnum;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.Enums;
using Lada.Framework.DTO.Models;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Lada.Framework.Infrastructures.Services;
using Lada.Framework.Infrastructures.Extensions;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Identity;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Medias;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Detail;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Updates;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Filters.Orders;
using Ladaer.BackEnd.Infrastructures.Services.Categories;
using Ladaer.BackEnd.Infrastructures.Services.Crm;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Data;
using Lada.Framework.Infrastructures;
using Lada.Framework.Infrastructures.Services;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Drawing;
using System.ComponentModel;
using System.Reflection;

namespace Ladaer.BackEnd.Infrastructures.Services.Orders
{
    /// <summary>
    /// Giao diện cho dịch vụ quản lý đơn hàng.
    /// </summary>
    public interface IOrderService
    {
        /// <summary>
        /// Tạo mới đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin đơn hàng.</param>
        /// <param name="apiKey">API key.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<OrderResult> Create(OrderModel model, string apiKey);

        /// <summary>
        /// Tìm kiếm đơn hàng.
        /// </summary>
        /// <param name="param">Thông số tìm kiếm.</param>
        /// <returns>Kết quả tìm kiếm đơn hàng.</returns>
        //Task<SmartTableResult<OrderItem>> Search(SmartTableParam param);

        Task<SmartTableResult<OrderItem>> Search(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy chi tiết đơn hàng theo mã đơn hàng.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        Task<OrderDetailModel> OrderDetailByCode(string code, CurrentUser currentUser);

        /// <summary>
        /// Lấy chi tiết đơn hàng theo mã đơn hàng với thông tin đơn vị đo.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng với đơn vị đo.</returns>
        Task<OrderDetailWithUnitsModel> OrderDetailByCodeWithUnits(string code, CurrentUser currentUser);

        /// <summary>
        /// Cập nhật trạng thái đơn hàng khi lấy hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<OrderTrackResult> PickupAsync(UpdateStatusModel model);

        /// <summary>
        /// Hủy đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> Cancel(UpdateStatusModel model);

        /// <summary>
        /// Gỡ bỏ trạng thái hủy của đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> RemoveCancel(UpdateStatusModel model);

        /// <summary>
        /// Xuất Excel danh sách đơn hàng.
        /// </summary>
        /// <param name="model">Model xuất Excel.</param>
        /// <returns>Kết quả xuất file.</returns>
        Task<OrderExcelExportResult> ExportOrdersAsync(OrderExcelExportModel model);

        /// <summary>
        /// Lấy đơn hàng theo ID.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <returns>Thông tin đơn hàng.</returns>
        Task<Order> GetByIdAsync(int orderId);

        /// <summary>
        /// Lấy thông tin chi tiết đơn hàng.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        Task<OrderDetailGeneralModel> GetOrderDetailGeneral(int orderId);

        /// <summary>
        /// Lấy thông tin chi tiết đơn hàng theo mã đơn hàng.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        Task<OrderDetailGeneralModel> GetOrderDetailGeneralByCode(string code);

        /// <summary>
        /// Chuẩn bị dữ liệu bộ lọc danh sách đơn hàng
        /// </summary>
        /// <param name="filter">Filter đầu vào để lấy thêm dữ liệu liên quan</param>
        /// <returns>Các danh sách option</returns>
        Task<OrderListFilter> PrepareOrderListFilterAsync(OrderListFilter filter);
    }

    /// <summary>
    /// Triển khai dịch vụ quản lý đơn hàng.
    /// </summary>
    public class OrderService : IOrderService
    {
        private static Random random = new Random();
        private readonly IDbConnection _dbConnection;

        private readonly IRepository<Order> _orderRepository;
        private readonly IRepository<OrderTrack> _orderTrackRepository;
        private readonly IRepository<Media> _mediaRepository;
        private readonly IFeeService _feeService;
        private readonly IOrderTrackService _orderTrackService;
        private readonly ILocationService _locationService;
        private readonly IUserService _userService;
        private readonly IUnifiedMediaService _unifiedMediaService;
        private readonly IVatInfoService _vatInfoService;
        private readonly ICustomerService _customerService;
        private readonly OrderFeeCalculationHelper _feeCalculationHelper;
        private readonly IExcelFileService _excelFileService;

        /// <summary>
        /// Khởi tạo một thể hiện của <see cref="OrderService"/>.
        /// </summary>
        /// <param name="dbConnection">Đối tượng IDbConnection.</param>
        /// <param name="feeService">Đối tượng IFeeService.</param>
        /// <param name="orderRepository">Đối tượng IRepository của Order.</param>
        /// <param name="orderTrackRepository">Đối tượng IRepository của OrderTrack.</param>
        /// <param name="mediaRepository">Đối tượng IRepository của Media.</param>
        /// <param name="locationService">Đối tượng ILocationService.</param>
        /// <param name="userService">Đối tượng IUserService.</param>
        /// <param name="orderTrackService">Đối tượng IOrderTrackService.</param>
        /// <param name="unifiedMediaService">Đối tượng IUnifiedMediaService.</param>
        /// <param name="vatInfoService">Đối tượng IVatInfoService.</param>
        /// <param name="feeCalculationHelper">Đối tượng OrderFeeCalculationHelper.</param>
        public OrderService(IDbConnection dbConnection, IFeeService feeService, IRepository<Order> orderRepository,
            IRepository<OrderTrack> orderTrackRepository, IRepository<Media> mediaRepository, ILocationService locationService, IUserService userService, IOrderTrackService orderTrackService, IUnifiedMediaService unifiedMediaService, IVatInfoService vatInfoService, OrderFeeCalculationHelper feeCalculationHelper, ICustomerService customerService, IExcelFileService excelFileService)
        {
            _dbConnection = dbConnection;
            _feeService = feeService;
            _orderRepository = orderRepository;
            _orderTrackRepository = orderTrackRepository;
            _mediaRepository = mediaRepository;
            _locationService = locationService;
            _userService = userService;
            _orderTrackService = orderTrackService;
            _unifiedMediaService = unifiedMediaService;
            _vatInfoService = vatInfoService;
            _feeCalculationHelper = feeCalculationHelper;
            _customerService = customerService;
            _excelFileService = excelFileService;
        }

        #region GET ORDER
        /// <summary>
        /// Lấy đơn hàng theo ID.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <returns>Thông tin đơn hàng.</returns>
        public async Task<Order> GetByIdAsync(int orderId)
        {
            var result = new Order();
            if (orderId > 0)
            {
                var order = await _orderRepository.Query().FirstOrDefaultAsync(o => o.Id == orderId);
                if (order != null && order.Id > 0)
                {
                    result = order;
                }
            }
            return result;
        }
        #endregion

        #region CREATE
        /// <summary>
        /// Tạo mới đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin đơn hàng.</param>
        /// <param name="apiKey">API key.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<OrderResult> Create(OrderModel model, string apiKey)
        {
            var result = new OrderResult();
            decimal totalWeight = 0;

            #region Chuẩn hóa trọng lượng sử dụng UnitConverter
            if (model.Packages != null && model.Packages.Any())
            {
                foreach (var package in model.Packages)
                {
                    var weightInGram = UnitConverter.ConvertWeightToGram(package.Weight);
                    var widthInMm = UnitConverter.ConvertDimensionToMillimeter(package.Width);
                    var lengthInMm = UnitConverter.ConvertDimensionToMillimeter(package.Length);
                    var heightInMm = UnitConverter.ConvertDimensionToMillimeter(package.Height);

                    package.Weight = weightInGram;
                    package.Width = widthInMm;
                    package.Length = lengthInMm;
                    package.Height = heightInMm;

                    decimal dimensionWeight = package.Width * package.Length * package.Height / 6000;
                    decimal chargeWeight = package.Weight >= dimensionWeight ? package.Weight : dimensionWeight;
                    package.SubTotalWeight = chargeWeight * package.Quantity;
                    totalWeight += package.SubTotalWeight;
                }
            }
            #endregion

            #region Validation VAT
            //if (!model.VatInfoId.HasValue || model.VatInfoId.Value <= 0)
            //{
            //    result.Result = Result.Failed;
            //    result.Message = "Vui lòng chọn thông tin xuất hóa đơn VAT khi yêu cầu xuất VAT";
            //    return result;
            //}

            // Kiểm tra VatInfo có tồn tại và thuộc về khách hàng này không
            if (model.OrderFin.VatInfoId.HasValue && model.OrderFin.VatInfoId.Value > 0)
            {
                var vatInfo = await _vatInfoService.GetByIdAsync(model.OrderFin.VatInfoId.Value);
                if (vatInfo == null || vatInfo.CustomerId != model.CustomerId)
                {
                    result.Result = Result.Failed;
                    result.Message = "Thông tin xuất hóa đơn VAT không hợp lệ hoặc không thuộc về khách hàng này";
                    return result;
                }

            }


            #endregion

            #region Tính cước
            model.OrderFin = await GetOrderFin(model, totalWeight, apiKey);
            if (model.OrderFin.Fee == 0)
            {
                result.Result = Result.Failed;
                result.Message = "Hệ thống tính cước gặp lỗi, vui lòng thử lại sau!";
                return result;
            }


            #endregion

            #region Địa chỉ
            model.SourceAddress.AddressType = AddressType.Source;
            model.DestAddress.AddressType = AddressType.Dest;
            var addresses = new List<OrderAddress>() {
                model.SourceAddress.ToEntity(),
                model.DestAddress.ToEntity()
            };
            #endregion

            var order = model.ToEntity();
            order = order.UpdateCommonInt(model.UpdatedBy, model.UpdatedByUserName);

            order.Addresses = addresses;
            if (order.Addresses.Any())
            {
                foreach (var item in order.Addresses)
                {
                    item.Id = 0;
                    item.CreatedByUserName = order.UpdatedByUserName;
                    item.CreatedBy = order.CreatedBy;
                    item.CreatedTime = DateTimeOffset.Now;
                    item.UpdatedBy = order.UpdatedBy;
                    item.UpdatedByUserName = order.UpdatedByUserName;
                    item.UpdatedTime = DateTimeOffset.Now;
                    item.OrderId = order.Id;
                }
            }
            if (order.Packages != null && order.Packages.Any())
            {
                foreach (var item in order.Packages)
                {
                    item.Id = 0;
                    item.UpdateCreation(order.UpdatedBy, order.UpdatedByUserName);
                    item.OrderId = order.Id;
                }
            }
            order.OrderOps = new OrderOps() { PickupNote = "", DeliveryNote = "", PicUserName = "", LastPicUserName = "", StatusContent = "", ReturnNote = "" };
            order.OrderTimeTrack = new OrderTimeTrack();
            order.OrderOps = (OrderOps)order.OrderOps.UpdateCreation(order.UpdatedBy, order.UpdatedByUserName);
            order.OrderFin = (OrderFin)order.OrderFin.UpdateCreation(order.UpdatedBy, order.UpdatedByUserName);

            return await Create(order);
        }

        /// <summary>
        /// Tạo mới đơn hàng.
        /// </summary>
        /// <param name="order">Thông tin đơn hàng.</param>
        /// <param name="retry">Số lần thử lại.</param>
        /// <returns>Kết quả của thao tác.</returns>
        private async Task<OrderResult> Create(Order order, int retry = 0)
        {
            var result = new OrderResult();

            var orderCode = await GenerateCodeAsync();
            order.Code = orderCode;
            try
            {
                int insertResult = await _orderRepository.InsertAsync(order);
                if (insertResult > 0)
                {
                    var trackModel = new OrderTrackModel()
                    {
                        OrderId = order.Id,
                        OrderCode = order.Code,
                        Name = "",
                        OrderTrackType = OrderTrackType.ForAll,
                        TrackActionType = TrackActionType.Add,
                        UpdatedBy = order.CreatedBy,
                        UpdatedByUserName = order.CreatedByUserName,
                        ActionSource = ActionSource.InternalWeb,
                        PhoneContact = ""
                    };

                    await _orderTrackService.CreateAsync(trackModel);
                    result.Result = Result.Success;
                }
                else
                {
                    result.Result = Result.Failed;
                    result.Message = "Hiện không thêm được đơn hàng, vui lòng thử lại sau";
                }
            }
            catch (Exception e)
            {
                if (retry < 3)
                {
                    // Có thể lỗi do mã bị trùng, thử lại 3 lần
                    result = await Create(order, retry + 1);
                }
                else
                {
                    result.Result = Result.Failed;
                    result.Message = e.Message;
                }
            }

            return result;
        }
        #endregion



        #region SEARCH WITH LIMIT
        /// <summary>
        /// Tìm kiếm đơn hàng.
        /// </summary>
        /// <param name="param">Thông số tìm kiếm.</param>
        /// <returns>Kết quả tìm kiếm đơn hàng.</returns>
        public async Task<SmartTableResult<OrderItem>> Search(SmartTableParam param, int userId)
        {
            SmartTableResult<OrderItem> gridData = new SmartTableResult<OrderItem>();
            var query = _orderRepository.Query();

            if (userId <= 0)
            {
                return gridData;
            }

            var roles = await _userService.GetRolesAsync(userId);

            if (!roles.Any(r => r == "Founder"))
            {
                query = query.Where(o => o.SaleId == userId || o.CreatedBy == userId);
            }

            if (param != null)
            {
                if (param.Search != null)
                {
                    if (param.Search.PredicateObject != null)
                    {
                        dynamic search = param.Search.PredicateObject;
                        if (search.Keyword != null)
                        {
                            string keyword = search.Keyword;
                            keyword = keyword.Trim();
                            if (!string.IsNullOrWhiteSpace(keyword))
                                query = query.Where(x => x.Code.Contains(keyword)
                                || x.PartnerCode.Contains(keyword)
                                || x.Addresses!.Any(oa => oa.PhoneNumber1 == keyword));
                        }
                        if (search.CustomerId != null)
                        {
                            int customerId;
                            if (int.TryParse(search.CustomerId.ToString(), out customerId) && customerId > 0)
                            {
                                query = query.Where(x => x.CustomerId == customerId);
                            }
                        }
                        if (search.OrderStatuses != null)
                        {
                            var statusIds = (JArray)search.OrderStatuses;
                            if (statusIds.Any())
                            {
                                var ids = statusIds.ToObject<List<OrderStatus>>();
                                query = query.Where(x => ids.Contains(x.OrderOps.Status));
                            }
                        }
                        if (search.OrderPhysicalStatuses != null)
                        {
                            var statusIds = (JArray)search.OrderPhysicalStatuses;
                            if (statusIds.Any())
                            {
                                var ids = statusIds.ToObject<List<OrderPhysicalStatus>>();
                                query = query.Where(x => ids.Contains(x.OrderOps.PhysicalStatus));
                            }
                        }
                        if (search.CreatedStart != null)
                        {
                            DateTimeOffset createStart = search.CreatedStart;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu ngày
                            var startOfDay = createStart.ToLocalTime().DateTime.StartOfDay();
                            query = query.Where(x => x.CreatedTime >= startOfDay);


                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày

                        }
                        if (search.CreatedEnd != null)
                        {
                            DateTimeOffset createEnd = search.CreatedEnd;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy cuối ngày
                            var endOfDay = createEnd.ToLocalTime().DateTime.EndOfDay();
                            query = query.Where(x => x.CreatedTime < endOfDay);
                        }
                        if (search.PayFeeTypes != null)
                        {
                            var payFeeTypeIds = (JArray)search.PayFeeTypes;
                            if (payFeeTypeIds.Any())
                            {
                                var ids = payFeeTypeIds.ToObject<List<PayFeeType>>();
                                query = query.Where(x => ids.Contains(x.OrderFin.PayFeeType));
                            }
                        }
                        if (search.PickupTimeStart != null)
                        {
                            DateTimeOffset pickupStart = search.PickupTimeStart;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu ngày
                            var startOfDay = pickupStart.ToLocalTime().DateTime.StartOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null && x.OrderTimeTrack.PickupTime >= startOfDay);
                        }
                        if (search.PickupTimeEnd != null)
                        {
                            DateTimeOffset pickupEnd = search.PickupTimeEnd;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy cuối ngày
                            var endOfDay = pickupEnd.ToLocalTime().DateTime.EndOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null && x.OrderTimeTrack.PickupTime <= endOfDay);
                        }
                        if (search.DeliveryTimeStart != null)
                        {
                            DateTimeOffset deliveryStart = search.DeliveryTimeStart;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu ngày
                            var startOfDay = deliveryStart.ToLocalTime().DateTime.StartOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null && x.OrderTimeTrack.DeliveryDate >= startOfDay);
                        }
                        if (search.DeliveryTimeEnd != null)
                        {
                            DateTimeOffset deliveryEnd = search.DeliveryTimeEnd;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy cuối ngày
                            var endOfDay = deliveryEnd.ToLocalTime().DateTime.EndOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null && x.OrderTimeTrack.DeliveryDate <= endOfDay);
                        }
                        if (search.HeadFeeTimeStart != null)
                        {
                            DateTimeOffset headFeeStart = search.HeadFeeTimeStart;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu ngày
                            var startOfDay = headFeeStart.ToLocalTime().DateTime.StartOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null &&
                                (x.OrderTimeTrack.HeadSourceFeeTime >= startOfDay ||
                                 x.OrderTimeTrack.HeadDestFeeTime >= startOfDay ||
                                 x.OrderTimeTrack.HeadTransferFeeTime >= startOfDay ||
                                 x.OrderTimeTrack.HeadDeductCodFeeTime >= startOfDay));
                        }
                        if (search.HeadFeeTimeEnd != null)
                        {
                            DateTimeOffset headFeeEnd = search.HeadFeeTimeEnd;
                            // Chuyển từ UTC sang local time (GMT+7) và lấy cuối ngày
                            var endOfDay = headFeeEnd.ToLocalTime().DateTime.EndOfDay();
                            query = query.Where(x => x.OrderTimeTrack != null &&
                                (x.OrderTimeTrack.HeadSourceFeeTime <= endOfDay ||
                                 x.OrderTimeTrack.HeadDestFeeTime <= endOfDay ||
                                 x.OrderTimeTrack.HeadTransferFeeTime <= endOfDay ||
                                 x.OrderTimeTrack.HeadDeductCodFeeTime <= endOfDay));
                        }


                    }
                }
                param.Sort = new Sort() { Predicate = "CreatedTime", Reverse = true };
                gridData = await query.Include(o => o.OrderFin)
                .Include(o => o.OrderOps)
                .Include(o => o.Addresses)
                .Include(o => o.Packages)
                .Include(o => o.OrderTimeTrack)
                .AsSplitQuery() // Thêm QuerySplittingBehavior để tối ưu hóa performance
                .ToSmartTableResultAsync(param, x => x.ToItem());

                // Tối ưu hóa: Sử dụng method helper để tránh duplicate code
                await EnrichOrderItemsAsync(gridData.Items);
            }

            return gridData;
        }
        #endregion

        #region TRACK
        /// <summary>
        /// Lấy chi tiết đơn hàng theo mã đơn hàng.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        public async Task<OrderDetailModel> OrderDetailByCode(string code, CurrentUser currentUser)
        {
            if (string.IsNullOrEmpty(code))
            {
                return new OrderDetailModel
                {
                    General = new OrderDetailGeneralModel
                    {
                        Code = "",
                        StatusContent = "",
                        RouteName = "",
                        CustomerName = "",
                        CustomerUserName = "",
                        PicUserName = ""
                    },
                    Finance = new OrderDetailFinModel(),
                    MediaItems = new List<MediaItem>()
                };
            }

            var order = await _orderRepository.Query()
                .Include(o => o.Customer)
                .Include(o => o.OrderOps)
                .Include(o => o.OrderFin)
                .Include(o => o.Tracks)
                .Include(o => o.Packages)
                .Include(o => o.Addresses)
                .AsSplitQuery() // Thêm QuerySplittingBehavior để tránh warning và cải thiện performance
                .Where(c => c.Code == code)
                .FirstOrDefaultAsync(o => o.Code == code);

            if (order == null)
            {
                return new OrderDetailModel
                {
                    General = new OrderDetailGeneralModel
                    {
                        Code = "",
                        StatusContent = "",
                        RouteName = "",
                        CustomerName = "",
                        CustomerUserName = "",
                        PicUserName = ""
                    },
                    Finance = new OrderDetailFinModel(),
                    MediaItems = new List<MediaItem>()
                };
            }

            var result = order.ToDetailModel();
            var manager = await _customerService.GetManagerById(order.CustomerId);
            var currentUserId = currentUser.UserId;
            result.Editable = manager.Id == currentUserId || order.SaleId == currentUserId;
            if (result.Tracks != null && result.Tracks.Any())
            {
                result.Tracks = result.Tracks.OrderByDescending(t => t.CreatedTime).ToList();
            }
            if (result.Addresses != null)
            {
                var wardIds = result.Addresses.Where(a => a.WardId > 0).Select(a => a.WardId).Distinct().ToList();
                var fullAddresses = await _locationService.GetFullAddress(wardIds, 3);
                int addIndex = 1;
                foreach (var address in result.Addresses)
                {
                    if (address.WardId > 0)
                    {
                        var fullAddress = fullAddresses.FirstOrDefault(f => f.Id == address.WardId);
                        if (fullAddress != null && fullAddress.Id > 0)
                        {

                            address.FullAddress = $"{address.Address1}, {fullAddress.FullAddress}";
                            if (addIndex == 1)
                            {
                                result.General.RouteName += fullAddress.CityName;
                            }
                            else
                            {
                                result.General.RouteName += $" - {fullAddress.CityName}";
                            }
                            addIndex++;
                        }
                    }
                }
            }

            // Lấy danh sách media theo OrderId - tối ưu hóa để tránh timeout
            result.MediaItems = await GetMediaByOrderIdOptimizedAsync(order.Id);

            return result;
        }

        /// <summary>
        /// Lấy chi tiết đơn hàng theo mã đơn hàng với thông tin đơn vị đo.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng với đơn vị đo.</returns>
        public async Task<OrderDetailWithUnitsModel> OrderDetailByCodeWithUnits(string code, CurrentUser currentUser)
        {
            if (string.IsNullOrEmpty(code))
            {
                return new OrderDetailWithUnitsModel
                {
                    General = new OrderDetailGeneralModel
                    {
                        Code = "",
                        StatusContent = "",
                        RouteName = "",
                        CustomerName = "",
                        CustomerUserName = "",
                        PicUserName = ""
                    },
                    Finance = new OrderDetailFinModel(),
                    MediaItems = new List<MediaItem>()
                };
            }

            var order = await _orderRepository.Query()
                .Include(o => o.Customer)
                .Include(o => o.OrderOps)
                .Include(o => o.OrderFin)
                .Include(o => o.Tracks)
                .Include(o => o.Packages)
                .Include(o => o.Addresses)
                .AsSplitQuery() // Thêm QuerySplittingBehavior để tránh warning và cải thiện performance
                .Where(c => c.Code == code)
                .FirstOrDefaultAsync(o => o.Code == code);

            if (order == null)
            {

                return new OrderDetailWithUnitsModel
                {
                    General = new OrderDetailGeneralModel
                    {
                        Code = "",
                        StatusContent = "",
                        RouteName = "",
                        CustomerName = "",
                        CustomerUserName = "",
                        PicUserName = ""
                    },
                    Finance = new OrderDetailFinModel(),
                    MediaItems = new List<MediaItem>()
                };
            }

            // Sử dụng existing OrderDetailModel mapping và convert packages
            var baseResult = order.ToDetailModel();
            var manager = await _customerService.GetManagerById(order.CustomerId);
            var currentUserId = currentUser.UserId;
            baseResult.Editable = manager.Id == currentUserId || order.SaleId == currentUserId;


            var result = new OrderDetailWithUnitsModel
            {
                Id = baseResult.Id,
                General = baseResult.General,
                Finance = baseResult.Finance,
                Addresses = baseResult.Addresses,
                Packages = order.Packages?.Select(p => p.ToResponseItem()).ToList() ?? new List<OrderPackageResponseItem>(),
                Tracks = baseResult.Tracks,
                MediaItems = new List<MediaItem>(),
                CreatedTime = baseResult.CreatedTime,
                UpdatedTime = baseResult.UpdatedTime,
                Editable = baseResult.Editable
            };

            if (result.Tracks != null && result.Tracks.Any())
            {
                result.Tracks = result.Tracks.OrderByDescending(t => t.CreatedTime).ToList();
            }
            if (result.Addresses != null)
            {
                var wardIds = result.Addresses.Where(a => a.WardId > 0).Select(a => a.WardId).Distinct().ToList();
                var fullAddresses = await _locationService.GetFullAddress(wardIds, 3);
                int addIndex = 1;
                foreach (var address in result.Addresses)
                {
                    if (address.WardId > 0)
                    {
                        var fullAddress = fullAddresses.FirstOrDefault(f => f.Id == address.WardId);
                        if (fullAddress != null && fullAddress.Id > 0)
                        {

                            address.FullAddress = $"{address.Address1}, {fullAddress.FullAddress}";
                            if (addIndex == 1)
                            {
                                result.General.RouteName += fullAddress.CityName;
                            }
                            else
                            {
                                result.General.RouteName += $" - {fullAddress.CityName}";
                            }
                            addIndex++;
                        }
                    }
                }
            }

            // Lấy danh sách media theo OrderId - tối ưu hóa để tránh timeout
            result.MediaItems = await GetMediaByOrderIdOptimizedAsync(order.Id);

            return result;
        }
        #endregion


        #region UPDATE STATUS
        /// <summary>
        /// Cập nhật trạng thái đơn hàng khi lấy hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<OrderTrackResult> PickupAsync(UpdateStatusModel model)
        {
            return await UpdateStatus(model);
        }

        /// <summary>
        /// Hủy đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<BaseResult> Cancel(UpdateStatusModel model)
        {
            model.NewStatus = OrderStatus.Cancelled;
            model.NewPhysicalStatus = OrderPhysicalStatus.Cancelled;
            model.ActionSource = ActionSource.InternalWeb;
            model.TrackActionType = TrackActionType.Cancel;
            model.OrderTrackType = OrderTrackType.ForAll;
            var order = await _orderRepository.Query().FirstOrDefaultAsync(c => c.Id == model.Id);
            if (order == null || order.Id <= 0)
            {
                return new BaseResult { Result = Result.Failed, Message = "Không tìm thấy đơn hàng yêu cầu" };
            }
            var manager = await _customerService.GetManagerById(order.CustomerId);
            if (manager.Id != model.UpdatedBy && order.SaleId != model.UpdatedBy)
            {
                return new BaseResult { Result = Result.Failed, Message = "Bạn không có quyền hủy đơn hàng không do mình tạo / quản lý" };
            }
            return await UpdateStatus(model);
        }

        /// <summary>
        /// Gỡ bỏ trạng thái hủy của đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<BaseResult> RemoveCancel(UpdateStatusModel model)
        {
            model.NewStatus = OrderStatus.New;
            model.NewPhysicalStatus = OrderPhysicalStatus.WaitToPickup;
            model.ActionSource = ActionSource.InternalWeb;
            model.TrackActionType = TrackActionType.UnCancel;
            model.OrderTrackType = OrderTrackType.ForAll;
            var order = await _orderRepository.Query().FirstOrDefaultAsync(c => c.Id == model.Id);
            if (order == null || order.Id <= 0)
            {
                return new BaseResult { Result = Result.Failed, Message = "Không tìm thấy đơn hàng yêu cầu" };
            }
            var manager = await _customerService.GetManagerById(order.CustomerId);
            if (manager.Id != model.UpdatedBy && order.SaleId != model.UpdatedBy)
            {
                return new BaseResult { Result = Result.Failed, Message = "Bạn không có quyền gỡ bỏ trạng thái hủy đơn hàng không do mình tạo / quản lý" };
            }
            return await UpdateStatus(model);
        }

        /// <summary>
        /// Cập nhật trạng thái đơn hàng.
        /// </summary>
        /// <param name="model">Thông tin cập nhật trạng thái.</param>
        /// <returns>Kết quả của thao tác.</returns>
        private async Task<OrderTrackResult> UpdateStatus(UpdateStatusModel model)
        {
            var result = new OrderTrackResult();
            if (model.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Yêu cầu không hợp lệ";
                return result;
            }
            var order = await _orderRepository.Query().Include(o => o.OrderOps).FirstOrDefaultAsync(c => c.Id == model.Id);

            if (order == null || order.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy đơn hàng yêu cầu";
                return result;
            }
            if (order.OrderOps == null || order.OrderOps.Id <= 0 || order.OrderOps.IsDeleted)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy thông tin triển khai của đơn hàng yêu cầu";
                return result;
            }

            if (model.NewStatus == order.OrderOps.Status && model.NewPhysicalStatus == order.OrderOps.PhysicalStatus)
            {
                result.Result = Result.Failed;
                result.Message = $"Trạng thái đơn hàng đang là: {model.NewStatus.GetDescription()} và {model.NewPhysicalStatus.GetDescription()}";
                return result;
            }
            var validUpdateStatus = ValidateUpdateStatus(order.OrderOps.Status, order.OrderOps.PhysicalStatus, model.NewStatus, model.NewPhysicalStatus);
            if (validUpdateStatus)
            {
                order.OrderOps.Status = model.NewStatus;
                order.OrderOps.PhysicalStatus = model.NewPhysicalStatus;
                order.OrderOps = (OrderOps)order.OrderOps.UpdateUpdation(model.UpdatedBy, model.UpdatedByUserName);

                order = order.UpdateCommonInt(model.UpdatedBy, model.UpdatedByUserName);

                try
                {
                    var udpResult = await _orderRepository.UpdateAsync(order);
                    if (udpResult <= 0)
                    {
                        result.Result = Result.SystemError;
                        result.Message = "Hệ thống không thể thực hiện yêu cầu lúc này, vui lòng thử lại sau!";
                        return result;
                    }
                    var trackModel = new OrderTrackModel()
                    {
                        OrderId = order.Id,
                        OrderCode = order.Code,
                        Name = model.Name,
                        OrderTrackType = model.OrderTrackType,
                        TrackActionType = model.TrackActionType,
                        UpdatedBy = model.UpdatedBy,
                        UpdatedByUserName = model.UpdatedByUserName,
                        ActionSource = model.ActionSource,
                        PhoneContact = "",
                    };
                    result = await _orderTrackService.CreateAsync(trackModel);
                }
                catch (Exception ex)
                {
                    result.Result = Result.SystemError;
                    result.Message = ex.ToString();
                }
            }
            return result;
        }

        /// <summary>
        /// Kiểm tra tính hợp lệ của việc cập nhật trạng thái đơn hàng.
        /// </summary>
        /// <param name="currentStatus">Trạng thái hiện tại của đơn hàng.</param>
        /// <param name="currentPhysicalStatus">Trạng thái vật lý hiện tại của đơn hàng.</param>
        /// <param name="newStatus">Trạng thái mới của đơn hàng.</param>
        /// <param name="newPhysicalStatus">Trạng thái vật lý mới của đơn hàng.</param>
        /// <returns>True nếu việc cập nhật trạng thái hợp lệ, ngược lại false.</returns>
        private bool ValidateUpdateStatus(OrderStatus currentStatus, OrderPhysicalStatus currentPhysicalStatus, OrderStatus newStatus, OrderPhysicalStatus newPhysicalStatus)
        {
            var result = false;
            switch (newStatus)
            {
                case OrderStatus.New:
                    if (currentStatus == OrderStatus.Cancelled && currentPhysicalStatus == OrderPhysicalStatus.Cancelled)
                    {
                        result = true;
                    }
                    break;
                case OrderStatus.Cancelled:
                    if (currentStatus == OrderStatus.New &&
                        (currentPhysicalStatus == OrderPhysicalStatus.WaitToPickup ||
                        currentPhysicalStatus == OrderPhysicalStatus.OnPicking))
                    {
                        result = true;
                    }
                    break;
                case OrderStatus.Received:
                    if (currentStatus == OrderStatus.New &&
                        (currentPhysicalStatus == OrderPhysicalStatus.WaitToPickup ||
                        currentPhysicalStatus == OrderPhysicalStatus.OnPicking))
                    {
                        result = true;
                    }
                    break;
                case OrderStatus.PickupFail:
                    break;
                case OrderStatus.DeliveryFail:
                    break;
                case OrderStatus.Delivered:
                    break;
                case OrderStatus.WaitToReturn:
                    break;
                case OrderStatus.ReturnFail:
                    break;
                case OrderStatus.Returned:
                    break;
                case OrderStatus.Unknown:
                    break;
                default:
                    break;
            }
            return result;
        }
        #endregion

        #region Utilities
        /// <summary>
        /// Tạo mã đơn hàng ngẫu nhiên.
        /// </summary>
        /// <param name="radVal">Giá trị ngẫu nhiên.</param>
        /// <returns>Mã đơn hàng.</returns>
        private async Task<string> GenerateCodeAsync(int radVal = 0)
        {
            // Lấy ngày hiện tại
            var currentDate = DateTime.Now;

            string currentDateStr = DateTime.Now.ToString("ddMM");
            var currentYear = int.Parse(currentDate.ToString("yy")) - 21;
            var currentDateFirstPart = currentDateStr.Substring(0, 2);
            var currentDateSecondPart = currentDateStr.Substring(2, 2);
            int randomValue = 0;

            if (radVal == 0)
            {
                randomValue = random.Next(38, 99);
            }
            else
            {
                randomValue = radVal;
            }

            int orderCount = 1338;

            // Lấy timestamp (số giây từ 1970)
            long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();

            try
            {
                // Lấy số lượng đơn hàng
                orderCount = (await _dbConnection.QueryFirstOrDefaultAsync<int>("Order_CountCreate", commandType: CommandType.StoredProcedure));
            }
            catch (Exception)
            {
                orderCount = 1338;
            }

            return $"{currentYear}{currentDateFirstPart}{randomValue}{currentDateSecondPart}{orderCount}";
        }

        /// <summary>
        /// Tính toán thông tin tài chính của đơn hàng.
        /// </summary>
        /// <param name="orderModel">Thông tin đơn hàng.</param>
        /// <param name="totalWeight">Tổng trọng lượng.</param>
        /// <param name="apiKey">API key.</param>
        /// <returns>Thông tin tài chính của đơn hàng.</returns>
        private async Task<OrderFinModel> GetOrderFin(OrderModel orderModel, decimal totalWeight, string apiKey)
        {
            var finModel = orderModel.OrderFin;

            // Sử dụng OrderFeeCalculationHelper để tính toán cước với VAT
            var feeResult = await _feeCalculationHelper.CalculateOrderFeeAsync(
                customerId: orderModel.CustomerId,
                sourceWardId: orderModel.SourceAddress.WardId,
                destWardId: orderModel.DestAddress.WardId,
                weight: totalWeight,
                collectAmount: finModel.CollectAmount,
                payFeeType: finModel.PayFeeType,
                pickupSubFee: finModel.PickupSubFee,
                deliverySubFee: finModel.DeliverySubFee,
                insuranceFee: finModel.InsuranceFee,
                discount: finModel.Discount,
                sourceFee: finModel.SourceFee,
                apiKey: apiKey
            );

            if (feeResult.Result != Result.Success)
            {
                finModel.Fee = 0;
                return finModel;
            }

            // Cập nhật finModel với kết quả tính toán
            finModel.Fee = feeResult.BaseFee;
            finModel.CodFee = feeResult.CodFee;
            finModel.VatFee = feeResult.VatFee;
            finModel.TotalFee = feeResult.TotalFeeAfterVat;
            finModel.SourceFee = feeResult.SourceFee;
            finModel.DestFee = feeResult.DestFee;
            finModel.TransferFee = feeResult.TransferFee;
            finModel.DeductCodFee = feeResult.DeductCodFee;
            return finModel;
        }

        /// <summary>
        /// Lấy thông tin chi tiết đơn hàng.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        public async Task<OrderDetailGeneralModel> GetOrderDetailGeneral(int orderId)
        {
            var order = await _orderRepository.Query().AsNoTracking()
                .Include(x => x.OrderOps)
                .Include(x => x.Customer)
                .FirstOrDefaultAsync(x => x.Id == orderId);

            if (order == null)
                return null;

            var result = new OrderDetailGeneralModel
            {
                Code = order.Code ?? "",
                Status = order.OrderOps?.Status ?? OrderStatus.New,
                PhysicalStatus = order.OrderOps?.PhysicalStatus ?? OrderPhysicalStatus.WaitToPickup,
                StatusContent = order.OrderOps?.StatusContent ?? "",
                RouteName = "",
                CustomerName = order.Customer?.FullName ?? "",
                CustomerUserName = order.Customer?.UserName ?? "",
                CustomerId = order.CustomerId,
                PicId = order.OrderOps?.PicId ?? 0,
                PicUserName = order.OrderOps?.PicUserName ?? "",
                CreatedTime = order.CreatedTime,
                UpdatedTime = order.UpdatedTime
            };

            return result;
        }

        /// <summary>
        /// Lấy thông tin chi tiết đơn hàng theo mã đơn hàng.
        /// </summary>
        /// <param name="code">Mã đơn hàng.</param>
        /// <returns>Thông tin chi tiết đơn hàng.</returns>
        public async Task<OrderDetailGeneralModel> GetOrderDetailGeneralByCode(string code)
        {
            var order = await _orderRepository.Query().AsNoTracking()
                .Include(x => x.OrderOps)
                .Include(x => x.Customer)
                .FirstOrDefaultAsync(x => x.Code == code);

            if (order == null)
                return null;

            var result = new OrderDetailGeneralModel
            {
                Code = order.Code ?? "",
                Status = order.OrderOps?.Status ?? OrderStatus.New,
                PhysicalStatus = order.OrderOps?.PhysicalStatus ?? OrderPhysicalStatus.WaitToPickup,
                StatusContent = order.OrderOps?.StatusContent ?? "",
                RouteName = "",
                CustomerName = order.Customer?.FullName ?? "",
                CustomerUserName = order.Customer?.UserName ?? "",
                CustomerId = order.CustomerId,
                PicId = order.OrderOps?.PicId ?? 0,
                PicUserName = order.OrderOps?.PicUserName ?? "",
                CreatedTime = order.CreatedTime,
                UpdatedTime = order.UpdatedTime
            };

            return result;
        }
        #endregion

        #region PRIVATE METHODS

        /// <summary>
        /// Lấy danh sách media theo Order ID
        /// </summary>
        /// <param name="orderId">ID của đơn hàng</param>
        /// <returns>Danh sách media items</returns>
        private async Task<List<MediaItem>> GetMediaByOrderIdAsync(int orderId)
        {
            var mediaItems = new List<MediaItem>();

            try
            {
                // Lấy tất cả media có OrderId hoặc OrderTrackId thuộc về order này
                var mediaList = await _mediaRepository.Query()
                    .Where(m => m.OrderId == orderId ||
                               _orderTrackRepository.Query().Any(ot => ot.OrderId == orderId && ot.Id == m.OrderTrackId))
                    .OrderBy(m => m.DisplayOrder)
                    .ThenBy(m => m.CreatedTime)
                    .ToListAsync();

                foreach (var media in mediaList)
                {
                    var mediaItem = new MediaItem
                    {
                        Id = media.Id,
                        Url = await _unifiedMediaService.GetUrlBySystemPathAsync(media.SystemPath),
                        AltText = media.AltText ?? string.Empty,
                        Caption = media.Caption ?? string.Empty,
                        DisplayOrder = media.DisplayOrder,
                        OrderId = media.OrderId,
                        OrderTrackId = media.OrderTrackId,
                        OrderPackageId = media.OrderPackageId
                    };

                    mediaItems.Add(mediaItem);
                }
            }
            catch (Exception)
            {
                // Log error if needed
                // For now, return empty list on error
                mediaItems = [];
            }

            return mediaItems;
        }

        /// <summary>
        /// Lấy danh sách media theo Order ID - tối ưu hóa để tránh timeout
        /// </summary>
        /// <param name="orderId">ID của đơn hàng</param>
        /// <returns>Danh sách media items</returns>
        private async Task<List<MediaItem>> GetMediaByOrderIdOptimizedAsync(int orderId)
        {
            var mediaItems = new List<MediaItem>();

            try
            {
                // Tối ưu hóa: Tách thành 2 query riêng biệt thay vì sử dụng subquery phức tạp

                // 1. Lấy media trực tiếp theo OrderId
                var directMedia = await _mediaRepository.Query()
                    .Where(m => m.OrderId == orderId)
                    .OrderBy(m => m.DisplayOrder)
                    .ThenBy(m => m.CreatedTime)
                    .ToListAsync();

                // 2. Lấy OrderTrackIds của order này
                var orderTrackIds = await _orderTrackRepository.Query()
                    .Where(ot => ot.OrderId == orderId)
                    .Select(ot => ot.Id)
                    .ToListAsync();

                // 3. Lấy media theo OrderTrackIds (chỉ nếu có OrderTracks)
                var trackMedia = new List<Lada.Framework.Data.Domains.Medias.Media>();
                if (orderTrackIds.Any())
                {
                    trackMedia = await _mediaRepository.Query()
                        .Where(m => orderTrackIds.Contains(m.OrderTrackId))
                        .OrderBy(m => m.DisplayOrder)
                        .ThenBy(m => m.CreatedTime)
                        .ToListAsync();
                }

                // 4. Kết hợp và loại bỏ trùng lặp
                var allMedia = directMedia.Union(trackMedia, new MediaComparer()).ToList();

                // 5. Tạo MediaItems
                foreach (var media in allMedia)
                {
                    var mediaItem = new MediaItem
                    {
                        Id = media.Id,
                        Url = await _unifiedMediaService.GetUrlBySystemPathAsync(media.SystemPath),
                        AltText = media.AltText ?? string.Empty,
                        Caption = media.Caption ?? string.Empty,
                        DisplayOrder = media.DisplayOrder,
                        OrderId = media.OrderId,
                        OrderTrackId = media.OrderTrackId,
                        OrderPackageId = media.OrderPackageId
                    };

                    mediaItems.Add(mediaItem);
                }
            }
            catch (Exception)
            {
                // Log error if needed
                // For now, return empty list on error
                mediaItems = [];
            }

            return mediaItems;
        }

        /// <summary>
        /// Comparer để so sánh Media entities
        /// </summary>
        private class MediaComparer : IEqualityComparer<Lada.Framework.Data.Domains.Medias.Media>
        {
            public bool Equals(Lada.Framework.Data.Domains.Medias.Media x, Lada.Framework.Data.Domains.Medias.Media y)
            {
                if (ReferenceEquals(x, y)) return true;
                if (ReferenceEquals(x, null)) return false;
                if (ReferenceEquals(y, null)) return false;
                return x.Id.Equals(y.Id);
            }

            public int GetHashCode(Lada.Framework.Data.Domains.Medias.Media obj)
            {
                return obj.Id.GetHashCode();
            }
        }

        /// <summary>
        /// Phục vụ cho cả 2 method Search để thêm thông tin địa chỉ và tên người bán
        /// </summary>
        /// <param name="orderItems">Danh sách OrderItem cần thêm thông tin.</param>
        /// <returns>Task.</returns>
        private async Task EnrichOrderItemsAsync(IEnumerable<OrderItem> orderItems)
        {
            if (orderItems == null || !orderItems.Any())
                return;

            var addresses = orderItems.SelectMany(i => i.Addresses).ToList();
            var wardIds = addresses.Where(a => a.WardId > 0).Select(a => a.WardId).Distinct().ToList();
            var fullAddresss = await _locationService.GetFullAddress(wardIds, 3);

            var saleIds = orderItems.Select(i => i.SaleId).ToList();
            var saleItems = new List<StaffItem>();
            if (saleIds != null && saleIds.Any())
            {
                saleItems = await _userService.GetByListIdAsync(saleIds);
            }

            foreach (var order in orderItems)
            {
                if (order.SaleId > 0)
                {
                    var sale = saleItems.FirstOrDefault(s => s.Id == order.SaleId);
                    if (sale != null && sale.Id > 0)
                    {
                        order.SaleUserName = sale.UserName;
                    }
                }
                int addIndex = 1;
                foreach (var address in order.Addresses)
                {
                    if (address.WardId > 0)
                    {
                        var fullAddress = fullAddresss.FirstOrDefault(f => f.Id == address.WardId);
                        if (fullAddress != null && fullAddress.Id > 0)
                        {
                            address.FullAddress = $"{address.Address1}, {fullAddress.FullAddress}";
                            if (addIndex == 1)
                            {
                                order.RouteName += fullAddress.CityName;
                            }
                            else
                            {
                                order.RouteName += $" - {fullAddress.CityName}";
                            }
                            addIndex++;
                        }
                    }
                }
            }
        }

        #endregion

        #region FILTER OPTIONS
        /// <summary>
        /// Chuẩn bị dữ liệu bộ lọc danh sách đơn hàng
        /// </summary>
        public async Task<OrderListFilter> PrepareOrderListFilterAsync(OrderListFilter filter)
        {
            var rs = filter ?? new OrderListFilter();

            rs.StatusOptions = Enum.GetValues<OrderStatus>()
                .Select(x => new FilterOption
                {
                    Id = (int)x,
                    Name = GetEnumDescription(x)
                })
                .OrderBy(x => x.Id)
                .ToList();

            rs.PhysicalStatusOptions = Enum.GetValues<OrderPhysicalStatus>()
                .Select(x => new FilterOption
                {
                    Id = (int)x,
                    Name = GetEnumDescription(x)
                })
                .OrderBy(x => x.Id)
                .ToList();

            rs.PayFeeTypeOptions = Enum.GetValues<OrderFinEnum.PayFeeType>()
                .Select(x => new FilterOption
                {
                    Id = (int)x,
                    Name = GetEnumDescription(x)
                })
                .OrderBy(x => x.Id)
                .ToList();

            // Nếu có CustomerId > 0 thì lấy thông tin khách hàng và đưa vào CustomerOptions
            if (rs.CustomerId > 0)
            {
                var customer = await _customerService.GetById(rs.CustomerId);
                if (customer != null && customer.Id > 0)
                {
                    rs.CustomerOptions = new List<CustomerOption>
                    {
                        new CustomerOption
                        {
                            Id = customer.Id,
                            FullName = customer.FullName ?? string.Empty,
                            PhoneNumber = customer.PhoneNumber ?? string.Empty,
                            UserName = customer.UserName ?? string.Empty
                        }
                    };
                }
            }

            return await Task.FromResult(rs);
        }

        private static string GetEnumDescription(Enum enumValue)
        {
            var field = enumValue.GetType().GetField(enumValue.ToString());
            var attribute = field?.GetCustomAttributes(typeof(DescriptionAttribute), false)
                .FirstOrDefault() as DescriptionAttribute;
            return attribute?.Description ?? enumValue.ToString();
        }
        #endregion

        #region EXCEL EXPORT

        /// <summary>
        /// Xuất Excel danh sách đơn hàng.
        /// </summary>
        /// <param name="model">Model xuất Excel.</param>
        /// <returns>Kết quả xuất file.</returns>
        public async Task<OrderExcelExportResult> ExportOrdersAsync(OrderExcelExportModel model)
        {
            var result = new OrderExcelExportResult
            {
                ProcessStartTime = DateTimeOffset.Now
            };

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

                // Tạo search param không có phân trang
                var searchParam = model.SearchParam;
                if (searchParam.Pagination != null)
                {
                    searchParam.Pagination = new Pagination
                    {
                        PageIndex = 1,
                        PageSize = int.MaxValue // Lấy tất cả
                    };
                }

                // Lấy dữ liệu đơn hàng
                var searchResult = await Search(searchParam, model.UpdatedBy);
                var orders = searchResult.Items.ToList();

                // Lấy thông tin thời gian từ database nếu cần
                if (model.IncludeTimeTrack && orders.Any())
                {
                    var orderIds = orders.Select(o => o.Id).ToList();
                    var timeTracks = await _orderRepository.Query()
                        .Where(o => orderIds.Contains(o.Id))
                        .Select(o => new { o.Id, o.OrderTimeTrack })
                        .ToListAsync();

                    // Tạo dictionary để lookup nhanh
                    var timeTrackDict = timeTracks.ToDictionary(t => t.Id, t => t.OrderTimeTrack);

                    // Gán thông tin thời gian vào orders (tạm thời lưu vào một property tạm)
                    foreach (var order in orders)
                    {
                        if (timeTrackDict.ContainsKey(order.Id))
                        {
                            // Tạo một property tạm để lưu thông tin thời gian
                            order.TimeTrack = timeTrackDict[order.Id];
                        }
                    }
                }

                // Tạo file Excel
                var excelPackage = await CreateOrderExcelPackageAsync(orders, model);

                // Tạo tên file
                var fileName = string.IsNullOrEmpty(model.FileName)
                    ? "DanhSachDonHang"
                    : model.FileName;

                // Lưu file sử dụng ExcelFileService
                var saveResult = await _excelFileService.SaveExcelFileAsync(
                    excelPackage,
                    fileName,
                    "orders",
                    model.FolderPath);

                if (saveResult.Result == Result.Success)
                {
                    // Cập nhật kết quả
                    result.FilePath = saveResult.FilePath;
                    result.FileName = saveResult.SavedFileName;
                    result.DownloadUrl = saveResult.FileUrl;
                    result.FileSize = saveResult.FileSize;
                    result.TotalRecords = orders.Count;
                    result.Result = Result.Success;
                    result.Message = "Xuất file Excel thành công";
                }
                else
                {
                    result.Result = saveResult.Result;
                    result.Message = saveResult.Message;
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi khi xuất file Excel: {ex.Message}";
            }

            result.ProcessEndTime = DateTimeOffset.Now;
            return result;
        }

        /// <summary>
        /// Tạo ExcelPackage danh sách đơn hàng
        /// </summary>
        private Task<ExcelPackage> CreateOrderExcelPackageAsync(List<OrderItem> orders, OrderExcelExportModel model)
        {
            var package = new ExcelPackage();
            var worksheet = package.Workbook.Worksheets.Add("Danh sách đơn hàng");

            // Thiết lập header
            SetupOrderHeaders(worksheet, model);

            // Điền dữ liệu
            FillOrderData(worksheet, orders, model);

            // Định dạng worksheet
            FormatOrderWorksheet(worksheet, orders.Count);

            return Task.FromResult(package);
        }

        /// <summary>
        /// Thiết lập header cho danh sách đơn hàng
        /// </summary>
        private void SetupOrderHeaders(ExcelWorksheet worksheet, OrderExcelExportModel model)
        {
            var headers = new List<string>
            {
                "STT", "Mã đơn hàng", "Mã đối tác", "Ngày tạo", "Trạng thái", "Trạng thái vật lý", "Phương thức thanh toán",
                "Tổng phí", "Số tiền thu", "Tên người gửi", "SĐT người gửi", "Địa chỉ gửi",
                "Tên người nhận", "SĐT người nhận", "Địa chỉ nhận"
            };

            if (model.IncludeTimeTrack)
            {
                headers.AddRange(new[]
                {
                    "Thời gian lấy hàng", "Thời gian giao hàng", "Thời gian nhận tiền lấy hàng", "Thời gian nhận tiền giao hàng",
                    "Thời gian nhận tiền chuyển khoản", "Thời gian nhận tiền cấn trừ COD"
                });
            }

            if (model.IncludePackages)
            {
                headers.AddRange(new[] { "Số gói hàng", "Tổng khối lượng" });
            }

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

        /// <summary>
        /// Điền dữ liệu danh sách đơn hàng
        /// </summary>
        private void FillOrderData(ExcelWorksheet worksheet, List<OrderItem> orders, OrderExcelExportModel model)
        {
            int row = 2; // Bắt đầu từ dòng 2 (dòng 1 là header)

            foreach (var order in orders)
            {
                int col = 1;

                // Thông tin cơ bản
                worksheet.Cells[row, col++].Value = row - 1; // STT
                worksheet.Cells[row, col++].Value = order.Code ?? "";
                worksheet.Cells[row, col++].Value = order.PartnerCode ?? "";
                worksheet.Cells[row, col++].Value = model.FormatDates
                    ? order.CreatedTime?.ToString("dd/MM/yyyy HH:mm")
                    : order.CreatedTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                worksheet.Cells[row, col++].Value = order.OrderOps?.StatusContent ?? "";
                worksheet.Cells[row, col++].Value = order.OrderOps?.PhysicalStatusStr ?? "";
                worksheet.Cells[row, col++].Value = order.OrderFin?.PayFeeTypeStr ?? "";
                worksheet.Cells[row, col++].Value = order.OrderFin?.TotalFee ?? 0;
                worksheet.Cells[row, col++].Value = order.OrderFin?.CollectAmount ?? 0;

                // Thông tin địa chỉ
                if (model.IncludeAddresses && order.Addresses != null && order.Addresses.Any())
                {
                    var senderAddress = order.Addresses.FirstOrDefault(a => a.AddressType == AddressType.Source);
                    var receiverAddress = order.Addresses.FirstOrDefault(a => a.AddressType == AddressType.Dest);

                    worksheet.Cells[row, col++].Value = senderAddress?.Name ?? "";
                    worksheet.Cells[row, col++].Value = senderAddress?.PhoneNumber1 ?? "";
                    worksheet.Cells[row, col++].Value = senderAddress?.FullAddress ?? "";
                    worksheet.Cells[row, col++].Value = receiverAddress?.Name ?? "";
                    worksheet.Cells[row, col++].Value = receiverAddress?.PhoneNumber1 ?? "";
                    worksheet.Cells[row, col++].Value = receiverAddress?.FullAddress ?? "";
                }
                else
                {
                    col += 6; // Skip address columns
                }

                // Thông tin thời gian
                if (model.IncludeTimeTrack)
                {
                    var timeTrack = order.TimeTrack;
                    if (timeTrack != null)
                    {
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.PickupTime?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.PickupTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.DeliveryDate?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.DeliveryDate?.ToString("yyyy-MM-ddTHH:mm:ss");
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.HeadSourceFeeTime?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.HeadSourceFeeTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.HeadDestFeeTime?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.HeadDestFeeTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.HeadTransferFeeTime?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.HeadTransferFeeTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                        worksheet.Cells[row, col++].Value = model.FormatDates
                            ? timeTrack.HeadDeductCodFeeTime?.ToString("dd/MM/yyyy HH:mm")
                            : timeTrack.HeadDeductCodFeeTime?.ToString("yyyy-MM-ddTHH:mm:ss");
                    }
                    else
                    {
                        worksheet.Cells[row, col++].Value = ""; // PickupTime
                        worksheet.Cells[row, col++].Value = ""; // DeliveryTime
                        worksheet.Cells[row, col++].Value = ""; // HeadSourceFeeTime
                        worksheet.Cells[row, col++].Value = ""; // HeadDestFeeTime
                        worksheet.Cells[row, col++].Value = ""; // HeadTransferFeeTime
                        worksheet.Cells[row, col++].Value = ""; // HeadDeductCodFeeTime
                    }
                }

                // Thông tin gói hàng
                if (model.IncludePackages && order.Packages != null)
                {
                    worksheet.Cells[row, col++].Value = order.Packages.Count();
                    worksheet.Cells[row, col++].Value = order.Packages.Sum(p => p.Weight);
                }
                else if (model.IncludePackages)
                {
                    col += 2; // Skip package columns
                }

                row++;
            }
        }

        /// <summary>
        /// Định dạng worksheet danh sách đơn hàng
        /// </summary>
        private void FormatOrderWorksheet(ExcelWorksheet worksheet, int dataRowCount)
        {
            // Định dạng header
            var headerRange = worksheet.Cells[1, 1, 1, worksheet.Dimension?.End.Column ?? 15];
            headerRange.Style.Font.Bold = true;
            headerRange.Style.Fill.PatternType = ExcelFillStyle.Solid;
            headerRange.Style.Fill.BackgroundColor.SetColor(Color.LightCoral);
            headerRange.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;

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

            // Định dạng border
            var dataRange = worksheet.Cells[1, 1, dataRowCount + 1, worksheet.Dimension?.End.Column ?? 15];
            dataRange.Style.Border.Top.Style = ExcelBorderStyle.Thin;
            dataRange.Style.Border.Left.Style = ExcelBorderStyle.Thin;
            dataRange.Style.Border.Right.Style = ExcelBorderStyle.Thin;
            dataRange.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
        }

        #endregion
    }
}

