using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Enums;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.Models;
using Lada.Framework.Infrastructures;
using Lada.Framework.Infrastructures.Helpers;
using Lada.Framework.Infrastructures.Services;
using Ladaer.BackEnd.Infrastructures.AppSettings;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Business.Operations;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Shared;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Ladaer.BackEnd.Infrastructures.Services.Crm;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using static Lada.Framework.Data.Enums.OrderFinEnum;

namespace Ladaer.BackEnd.Infrastructures.Services.Orders
{
    /// <summary>
    /// Interface để định nghĩa các phương thức xử lý tài chính đơn hàng.
    /// </summary>
    public interface IOrderFinService
    {
        /// <summary>
        /// Cập nhật tài chính đơn hàng không đồng bộ.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <param name="updatedBy">ID của người cập nhật.</param>
        /// <param name="updatedByUserName">Tên người cập nhật.</param>
        /// <returns>Kết quả của hoạt động cập nhật.</returns>
        Task<BaseResult> UpdateOrderFinAsync(int orderId, int updatedBy, string updatedByUserName);

        /// <summary>
        /// Lấy thông tin tài chính đơn hàng dựa trên ID.
        /// </summary>
        /// <param name="id">ID của tài chính đơn hàng.</param>
        /// <returns>Thông tin tài chính đơn hàng.</returns>
        Task<UpdateOrderFinModel> GetById(int id);

        /// <summary>
        /// Cập nhật thông tin tài chính đơn hàng.
        /// </summary>
        /// <param name="model">Model chứa thông tin tài chính đơn hàng.</param>
        /// <returns>Kết quả của hoạt động cập nhật.</returns>
        Task<BaseResult> Update(UpdateOrderFinModel model);

        /// <summary>
        /// Thu tiền
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<BaseResult> Collect(CollectMoneyModel model);
    }

    /// <summary>
    /// Lớp triển khai các phương thức xử lý tài chính đơn hàng.
    /// </summary>
    public class OrderFinService : IOrderFinService
    {
        private readonly IRepository<Order> _orderRepository;
        private readonly IRepository<OrderFin> _orderFinRepository;
        private readonly IRepository<OrderPackage> _orderPackageRepository;
        private readonly IFeeService _feeService;
        private readonly IOrderTrackService _orderTrackService;
        private readonly IUserService _userService;
        private readonly ICustomerService _customerService;
        private readonly string _mapApiKey;

        /// <summary>
        /// Khởi tạo một instance mới của lớp <see cref="OrderFinService"/>.
        /// </summary>
        /// <param name="options">Tùy chọn cấu hình ứng dụng.</param>
        /// <param name="orderRepository">Kho lưu trữ đơn hàng.</param>
        /// <param name="feeService">Dịch vụ tính phí.</param>
        /// <param name="orderFinRepository">Kho lưu trữ tài chính đơn hàng.</param>
        /// <param name="orderPackageRepository">Kho lưu trữ kiện hàng.</param>
        /// <param name="orderTrackService">Dịch vụ theo dõi đơn hàng.</param>
        /// <param name="userService">Dịch vụ người dùng.</param>
        public OrderFinService(IOptions<AppSetting> options, IRepository<Order> orderRepository, IFeeService feeService,
            IRepository<OrderFin> orderFinRepository, IRepository<OrderPackage> orderPackageRepository,
            IOrderTrackService orderTrackService, IUserService userService, ICustomerService customerService)
        {
            _orderRepository = orderRepository;
            _orderFinRepository = orderFinRepository;
            _orderPackageRepository = orderPackageRepository;
            _feeService = feeService;
            _orderTrackService = orderTrackService;
            _userService = userService;
            _customerService = customerService;
            _mapApiKey = options.Value.GoogleMapsApi.ApiKey;
        }

        /// <summary>
        /// Lấy thông tin tài chính đơn hàng dựa trên ID.
        /// </summary>
        /// <param name="id">ID của tài chính đơn hàng.</param>
        /// <returns>Thông tin tài chính đơn hàng.</returns>
        public async Task<UpdateOrderFinModel> GetById(int id)
        {
            var result = new UpdateOrderFinModel();
            if (id <= 0)
            {
                return result;
            }
            var orderFin = await _orderFinRepository.Query().FirstOrDefaultAsync(c => c.Id == id);
            if (orderFin == null || orderFin.Id <= 0)
            {
                return result;
            }
            result = orderFin.ToUpdateModel();
            return result;
        }

        /// <summary>
        /// Cập nhật thông tin tài chính đơn hàng.
        /// </summary>
        /// <param name="model">Model chứa thông tin tài chính đơn hàng.</param>
        /// <returns>Kết quả của hoạt động cập nhật.</returns>
        public async Task<BaseResult> Update(UpdateOrderFinModel model)
        {
            var result = new BaseResult();
            var orderFin = await _orderFinRepository.Query().Include(oa => oa.Order).FirstOrDefaultAsync(c => c.Id == model.Id);
            string oldvalue = JsonConvert.SerializeObject(orderFin, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
            if (orderFin == null || orderFin.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy thông tin yêu cầu!";
                return result;
            }

            var manager = await _customerService.GetManagerById(orderFin.Order.CustomerId);
            if (manager.Id != model.UpdatedBy && orderFin.Order.SaleId != model.UpdatedBy)
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền cập nhật tài chính đơn hàng không do mình tạo / quản lý";
                return result;
            }

            // Kiểm tra xem đã có người thu tiền hay chưa
            if (orderFin.SourceFeeCashierId > 0 ||
                orderFin.DestFeeCashierId > 0 ||
                orderFin.CodCashierId > 0 ||
                orderFin.TransferFeeCashierId > 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không thể sửa đổi thông tin tài chính vì đã có người thu tiền!";
                return result;
            }

            try
            {
                orderFin.CollectAmount = model.CollectAmount;
                orderFin.PickupSubFee = model.PickupSubFee;
                orderFin.DeliverySubFee = model.DeliverySubFee;
                orderFin.Discount = model.Discount;
                orderFin.PayFeeType = model.PayFeeType;
                // Kiểm tra xem có phí thu hộ hay không, nếu có thì lấy 1%
                if (orderFin.CollectAmount > 1000000)
                {
                    orderFin.CodFee = orderFin.CollectAmount / 100;
                }
                else
                {
                    orderFin.CodFee = 0;
                }

                // Tổng phí = phí vận chuyển + phí COD - giảm giá
                //orderFin.TotalFee = orderFin.Fee + orderFin.CodFee + orderFin.PickupSubFee + orderFin.DeliverySubFee - orderFin.Discount;

                // Loại thu phí
                switch (orderFin.PayFeeType)
                {
                    case PayFeeType.SenderPay:
                        orderFin.SourceFee = orderFin.TotalFee;
                        orderFin.DestFee = 0;
                        orderFin.TransferFee = 0;
                        orderFin.DeductCodFee = 0;
                        break;
                    case PayFeeType.ConsigneePay:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = orderFin.TotalFee;
                        orderFin.TransferFee = 0;
                        orderFin.DeductCodFee = 0;
                        break;
                    case PayFeeType.BankTransfer:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = 0;
                        orderFin.TransferFee = orderFin.TotalFee;
                        orderFin.DeductCodFee = 0;
                        break;
                    case PayFeeType.SplitPay:
                        orderFin.SourceFee = model.SourceFee;
                        orderFin.DestFee = orderFin.TotalFee - orderFin.SourceFee;
                        orderFin.TransferFee = 0;
                        orderFin.DeductCodFee = 0;
                        break;
                    case PayFeeType.COD:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = 0;
                        orderFin.TransferFee = 0;
                        orderFin.DeductCodFee = orderFin.TotalFee;
                        break;
                    default:
                        break;
                }

                orderFin = (OrderFin)orderFin.UpdateUpdation(model.UpdatedBy, model.UpdatedByUserName);

                string newvalue = JsonConvert.SerializeObject(orderFin, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });

                await _orderFinRepository.UpdateAsync(orderFin);

                #region Hành trình
                var trackModel = new OrderTrackModel()
                {
                    OrderId = orderFin.Id,
                    OrderCode = orderFin.Order.Code,
                    Name = "Cập nhật tài chính",
                    OrderTrackType = OrderTrackType.ForAll,
                    TrackActionType = TrackActionType.Update,
                    UpdatedBy = model.UpdatedBy,
                    UpdatedByUserName = model.UpdatedByUserName,
                    ActionSource = ActionSource.InternalWeb,
                    PhoneContact = "",
                    DataBefore = oldvalue,
                    DataAfter = newvalue
                };
                await _orderTrackService.CreateAsync(trackModel);
                #endregion
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Cập nhật tài chính đơn hàng không đồng bộ.
        /// </summary>
        /// <param name="orderId">ID của đơn hàng.</param>
        /// <param name="updatedBy">ID của người cập nhật.</param>
        /// <param name="updatedByUserName">Tên người cập nhật.</param>
        /// <returns>Kết quả của hoạt động cập nhật.</returns>
        public async Task<BaseResult> UpdateOrderFinAsync(int orderId, int updatedBy, string updatedByUserName)
        {
            var result = new BaseResult();

            try
            {
                // Lấy thông tin đơn hàng với các thông tin liên quan
                var order = await _orderRepository.Query()
                                    .Include(o => o.Addresses)
                                    .Include(o => o.Packages.Where(p => !p.IsDeleted))
                                    .Where(o => o.Id == orderId).FirstOrDefaultAsync();

                if (order == null || order.Id <= 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy đơn hàng";
                    return result;
                }

                // Lấy thông tin tài chính để kiểm tra
                var existingOrderFin = await _orderFinRepository.Query().FirstOrDefaultAsync(f => f.Id == orderId);
                if (existingOrderFin != null && (existingOrderFin.SourceFeeCashierId > 0 || existingOrderFin.DestFeeCashierId > 0 || existingOrderFin.CodCashierId > 0))
                {
                    result.Result = Result.Failed;
                    result.Message = "Không thể tính toán lại cước phí vì đã có người thu tiền!";
                    return result;
                }

                // Tính toán trọng lượng tính cước
                decimal totalWeight = 0;
                var weightDebugInfo = new List<string>();

                if (order.Packages != null && order.Packages.Any())
                {
                    foreach (var package in order.Packages)
                    {
                        // Tính trọng lượng theo thể tích (gram) - giống như hệ thống hiện tại
                        decimal dimensionWeight = (decimal)(package.Length * package.Width * package.Height) / 6000; // mm³ to gram
                        // Tính trọng lượng thực tế (gram)
                        decimal actualWeight = (decimal)package.Weight; // đã là gram
                        // Lấy trọng lượng lớn hơn để tính cước (gram)
                        decimal chargeWeight = Math.Max(actualWeight, dimensionWeight);
                        // Cập nhật trọng lượng tính cước cho package
                        package.SubTotalWeight = (int)(chargeWeight * package.Quantity); // gram
                        totalWeight += chargeWeight * package.Quantity; // gram

                        // Debug info
                        weightDebugInfo.Add($"Package {package.Id}: Actual={actualWeight:F0}g, Dimension={dimensionWeight:F0}g, Charge={chargeWeight:F0}g, Qty={package.Quantity}, Total={chargeWeight * package.Quantity:F0}g");
                    }
                }

                if (totalWeight <= 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tính toán được trọng lượng đơn hàng";
                    return result;
                }

                // Kiểm tra địa chỉ nguồn và đích
                if (order.Addresses == null || !order.Addresses.Any())
                {
                    result.Result = Result.Failed;
                    result.Message = "Đơn hàng không có địa chỉ";
                    return result;
                }

                var sourceAddress = order.Addresses.FirstOrDefault(a => a.AddressType == AddressType.Source);
                var destAddress = order.Addresses.FirstOrDefault(a => a.AddressType == AddressType.Dest);

                if (sourceAddress == null || destAddress == null ||
                    sourceAddress.WardId <= 0 || destAddress.WardId <= 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Địa chỉ nguồn hoặc đích trên đơn không hợp lệ";
                    return result;
                }

                // Tính cước vận chuyển
                var feeModel = new FeeByWardModel()
                {
                    CustomerId = order.CustomerId,
                    SourceWardId = sourceAddress.WardId,
                    DestWardId = destAddress.WardId,
                    Weight = totalWeight // đã là gram
                };

                var feeResult = await _feeService.GetFeeByWard(feeModel, _mapApiKey);
                if (feeResult.Result != Result.Success)
                {
                    result.Result = Result.Failed;
                    result.Message = $"Không tính được phí: {feeResult.Message}";
                    return result;
                }

                // Lấy thông tin tài chính đơn hàng
                var orderFin = await _orderFinRepository.Query().FirstOrDefaultAsync(o => o.Id == order.Id);
                if (orderFin == null || orderFin.Id <= 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy thông tin tài chính đơn hàng";
                    return result;
                }

                // Lưu cước cũ để tracking
                var oldTotalFee = orderFin.TotalFee;
                var oldFee = orderFin.Fee;

                // Cập nhật cước vận chuyển mới
                orderFin.Fee = feeResult.Fee;

                // Tính phí COD (1% nếu thu hộ > 1,000,000)
                if (orderFin.CollectAmount > 1000000)
                {
                    orderFin.CodFee = orderFin.CollectAmount / 100;
                }
                else
                {
                    orderFin.CodFee = 0;
                }

                // Tính lại tổng phí (TotalFee được tính tự động trong property)
                var newTotalFee = orderFin.TotalFee;

                // Phân bổ phí theo loại thanh toán
                switch (orderFin.PayFeeType)
                {
                    case PayFeeType.SenderPay:
                        orderFin.SourceFee = newTotalFee;
                        orderFin.DestFee = 0;
                        break;
                    case PayFeeType.ConsigneePay:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = newTotalFee;
                        break;
                    case PayFeeType.BankTransfer:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = 0;
                        orderFin.TransferFee = newTotalFee;
                        break;
                    case PayFeeType.COD:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = 0;
                        orderFin.TransferFee = 0;
                        orderFin.DeductCodFee = newTotalFee;
                        break;
                    case PayFeeType.SplitPay:
                        // Giữ nguyên SourceFee, tính lại DestFee
                        orderFin.DestFee = newTotalFee - orderFin.SourceFee;
                        if (orderFin.DestFee < 0) orderFin.DestFee = 0;
                        break;
                    default:
                        orderFin.SourceFee = 0;
                        orderFin.DestFee = newTotalFee;
                        break;
                }

                // Cập nhật thông tin người sửa
                order = order.UpdateCommonInt(updatedBy, updatedByUserName);
                orderFin = (OrderFin)orderFin.UpdateUpdation(updatedBy, updatedByUserName);

                // Lưu vào database
                await _orderRepository.UpdateAsync(order);
                await _orderFinRepository.UpdateAsync(orderFin);

                // Cập nhật SubTotalWeight cho các packages
                foreach (var package in order.Packages)
                {
                    package.UpdatedBy = updatedBy;
                    package.UpdatedByUserName = updatedByUserName;
                    package.UpdatedTime = DateTimeHelper.CurrentTime();
                    await _orderPackageRepository.UpdateAsync(package);
                }

                // Ghi tracking nếu có thay đổi cước
                if (oldTotalFee != newTotalFee)
                {
                    var trackModel = new OrderTrackModel()
                    {
                        OrderId = order.Id,
                        OrderCode = order.Code,
                        Name = $"Tính lại cước: {oldTotalFee.FormatCurrency()} → {newTotalFee.FormatCurrency()}",
                        OrderTrackType = OrderTrackType.ForInternal,
                        TrackActionType = TrackActionType.Update,
                        PicId = updatedBy,
                        PicUserName = updatedByUserName,
                        UpdatedBy = updatedBy,
                        UpdatedByUserName = updatedByUserName,
                        ActionSource = ActionSource.InternalWeb,
                        PhoneContact = "",
                        DataBefore = $"Cước cũ: {oldTotalFee.FormatCurrency()} (Phí VC: {oldFee.FormatCurrency()})",
                        DataAfter = $"Cước mới: {newTotalFee.FormatCurrency()} (Phí VC: {orderFin.Fee.FormatCurrency()}, COD: {orderFin.CodFee.FormatCurrency()}) | Trọng lượng: {totalWeight:F0}g ({totalWeight / 1000:F2}kg) | {string.Join("; ", weightDebugInfo)}"
                    };
                    await _orderTrackService.CreateAsync(trackModel);
                }
                else
                {
                    // Ghi tracking để debug khi cước không thay đổi
                    var trackModel = new OrderTrackModel()
                    {
                        OrderId = order.Id,
                        OrderCode = order.Code,
                        Name = $"Tính lại cước - Không thay đổi: {newTotalFee.FormatCurrency()}",
                        OrderTrackType = OrderTrackType.ForInternal,
                        TrackActionType = TrackActionType.Update,
                        PicId = updatedBy,
                        PicUserName = updatedByUserName,
                        UpdatedBy = updatedBy,
                        UpdatedByUserName = updatedByUserName,
                        ActionSource = ActionSource.InternalWeb,
                        PhoneContact = "",
                        DataBefore = $"Trọng lượng: {totalWeight:F0}g ({totalWeight / 1000:F2}kg)",
                        DataAfter = $"Phí VC: {orderFin.Fee.FormatCurrency()}, COD: {orderFin.CodFee.FormatCurrency()} | {string.Join("; ", weightDebugInfo)}"
                    };
                    await _orderTrackService.CreateAsync(trackModel);
                }

                result.Result = Result.Success;
                result.Message = $"Cập nhật cước thành công. Cước mới: {newTotalFee.FormatCurrency()} (Trọng lượng: {totalWeight / 1000:F2}kg)";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống khi tính lại cước: {ex.Message}";
            }

            return result;
        }


        /// <summary>
        /// Thu tiền
        /// </summary>
        /// <param name="model">Model chứa thông tin thu tiền của đơn hàng.</param>
        /// <returns>Kết quả của hoạt động cập nhật.</returns>
        public async Task<BaseResult> Collect(CollectMoneyModel model)
        {
            var result = new BaseResult();
            var orderFin = await _orderFinRepository.Query().FirstOrDefaultAsync(c => c.Id == model.Id);
            var order = await _orderRepository.Query().Include(o => o.OrderOps).FirstOrDefaultAsync(c => c.Id == model.Id);
            var orderFeeStage = await GetFeeStageByUserId(model.UpdatedBy);
            decimal totalCollect = 0;
            if (order != null && order.Id > 0 && orderFin != null && orderFin.Id > 0 && order.OrderOps != null && order.OrderOps.Id > 0)
            {

                switch (model.Type)
                {
                    case CollectMoneyType.FromSender:
                        if (order.OrderOps.PhysicalStatus == OrderPhysicalStatus.OnPicking)
                        {
                            // Set current cashier
                            orderFin.SourceFeeCashierId = model.UpdatedBy;
                            orderFin.SourceFeeCashierUsername = model.UpdatedByUserName;
                            orderFin.SourceFeeStage = orderFeeStage;

                            // Set original cashier if not set yet (first time collecting)
                            if (orderFin.OriginalSourceFeeCashierId == null)
                            {
                                orderFin.OriginalSourceFeeCashierId = model.UpdatedBy;
                                orderFin.OriginalSourceFeeCashierUsername = model.UpdatedByUserName;
                                orderFin.SourceFeeCollectedTime = DateTimeOffset.Now;
                            }
                            switch (orderFin.PayFeeType)
                            {
                                case PayFeeType.SenderPay:
                                    totalCollect = orderFin.TotalFee;
                                    break;
                                case PayFeeType.ConsigneePay:
                                    totalCollect = orderFin.TotalFee;
                                    orderFin.PayFeeType = PayFeeType.SenderPay;
                                    break;
                                case PayFeeType.BankTransfer:
                                    totalCollect = orderFin.TotalFee;
                                    orderFin.PayFeeType = PayFeeType.SenderPay;
                                    break;
                                case PayFeeType.SplitPay:
                                    totalCollect = orderFin.SourceFee;
                                    break;
                                default:
                                    result.Result = Result.Failed;
                                    result.Message = $"Không xác định được kiểu thu tiền";
                                    return result;
                            }
                            //Trong trường hợp người gửi trả cước mà loại trả cước khác người gửi vẫn cho thu cước bt

                        }
                        else
                        {
                            result.Result = Result.Failed;
                            result.Message = $"Trạng thái đơn hàng không hợp lệ, trạng thái hiện tại là {order.OrderOps.Status.GetDescription()} và {order.OrderOps.PhysicalStatus.GetDescription()}";
                        }
                        break;
                    case CollectMoneyType.FromReceiver:
                        if (order.OrderOps.PhysicalStatus == OrderPhysicalStatus.OnDelivery)
                        {
                            // Set current cashier
                            orderFin.DestFeeCashierId = model.UpdatedBy;
                            orderFin.DestFeeCashierUsername = model.UpdatedByUserName;
                            orderFin.CodCashierId = model.UpdatedBy;
                            orderFin.CodCashierUsername = model.UpdatedByUserName;
                            orderFin.DestFeeStage = orderFeeStage;

                            // Set original cashier if not set yet (first time collecting)
                            if (orderFin.OriginalDestFeeCashierId == null)
                            {
                                orderFin.OriginalDestFeeCashierId = model.UpdatedBy;
                                orderFin.OriginalDestFeeCashierUsername = model.UpdatedByUserName;
                                orderFin.DestFeeCollectedTime = DateTimeOffset.UtcNow;
                            }

                            if (orderFin.OriginalCodCashierId == null)
                            {
                                orderFin.OriginalCodCashierId = model.UpdatedBy;
                                orderFin.OriginalCodCashierUsername = model.UpdatedByUserName;
                                orderFin.CodCollectedTime = DateTimeOffset.UtcNow;
                            }
                            if (orderFeeStage == OrderFeeStage.Head)
                            {
                                orderFin.CodStage = OrderCodStage.Head;
                            }
                            else
                            {
                                orderFin.CodStage = OrderCodStage.Branch;
                            }
                            switch (orderFin.PayFeeType)
                            {
                                case PayFeeType.SenderPay:
                                    orderFin.PayFeeType = PayFeeType.ConsigneePay;
                                    totalCollect = orderFin.TotalFee + orderFin.CollectAmount;
                                    break;
                                case PayFeeType.ConsigneePay:
                                    totalCollect = orderFin.TotalFee + orderFin.CollectAmount;

                                    break;
                                case PayFeeType.BankTransfer:
                                    totalCollect = orderFin.TotalFee + orderFin.CollectAmount;
                                    orderFin.PayFeeType = PayFeeType.ConsigneePay;
                                    break;
                                case PayFeeType.SplitPay:
                                    totalCollect = orderFin.DestFee + orderFin.CollectAmount;
                                    break;
                                default:
                                    result.Result = Result.Failed;
                                    result.Message = $"Không xác định được kiểu thu tiền";
                                    return result;
                            }
                        }
                        else
                        {
                            result.Result = Result.Failed;
                            result.Message = $"Trạng thái đơn hàng không hợp lệ, trạng thái hiện tại là {order.OrderOps.Status.GetDescription()} và {order.OrderOps.PhysicalStatus.GetDescription()}";
                        }
                        break;

                    default:
                        break;
                }

                await _orderFinRepository.UpdateAsync(orderFin);

                #region Hành trình
                var trackModel = new OrderTrackModel()
                {
                    OrderId = order.Id,
                    OrderCode = order.Code,
                    Name = $"{model.UpdatedByUserName} thu {totalCollect.FormatCurrency()}",
                    OrderTrackType = OrderTrackType.ForInternal,
                    TrackActionType = TrackActionType.CollectMoney,
                    PicId = model.UpdatedBy,
                    PicUserName = model.UpdatedByUserName,
                    UpdatedBy = model.UpdatedBy,
                    UpdatedByUserName = model.UpdatedByUserName,
                    ActionSource = ActionSource.InternalWeb,
                    PhoneContact = ""
                };
                await _orderTrackService.CreateAsync(trackModel);
                #endregion
            }
            else
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy đơn hàng";
            }

            return result;
        }


        private async Task<OrderFeeStage> GetFeeStageByUserId(int userId)
        {
            var result = OrderFeeStage.Branch;
            var userRoles = await _userService.GetRolesAsync(userId);
            var headRoles = new List<string>() { "FOUNDER,CO-FOUNDER,ACCOUNTANT" };
            var branchRoles = new List<string>() { "COORDINATOR" };
            var driverRole = new List<string>() { "DRIVER" };
            if (userRoles.Any())
            {
                var upperUserRoles = userRoles.Select(u => u.ToUpper()).ToList();
                if (upperUserRoles.Any(headRoles.Contains))
                {
                    return OrderFeeStage.Head;
                }
                if (upperUserRoles.Any(driverRole.Contains))
                {
                    return OrderFeeStage.Driver;
                }
            }
            return result;
        }
    }
}
