using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.DTO;
using Lada.Framework.Infrastructures.Extensions;
using static Lada.Framework.Data.Enums.OrderFinEnum;

namespace Lada.Framework.Infrastructures.Services
{
    /// <summary>
    /// Helper class để tích hợp OrderFeeCalculationService vào các service hiện tại
    /// </summary>
    public class OrderFeeCalculationHelper
    {
        private readonly IOrderFeeCalculationService _feeCalculationService;

        public OrderFeeCalculationHelper(IOrderFeeCalculationService feeCalculationService)
        {
            _feeCalculationService = feeCalculationService;
        }

        /// <summary>
        /// Tính toán và cập nhật cước cho đơn hàng mới
        /// </summary>
        /// <param name="orderFin">OrderFin entity</param>
        /// <param name="customerId">ID khách hàng</param>
        /// <param name="sourceWardId">ID phường/xã nguồn</param>
        /// <param name="destWardId">ID phường/xã đích</param>
        /// <param name="weight">Trọng lượng (gram)</param>
        /// <param name="apiKey">API key</param>
        /// <returns>Kết quả tính toán</returns>
        public async Task<OrderFeeCalculationResult> CalculateAndUpdateOrderFeeAsync(
            OrderFin orderFin,
            int customerId,
            int sourceWardId,
            int destWardId,
            decimal weight,
            string apiKey = "")
        {
            var request = orderFin.ToCalculationRequest(customerId, sourceWardId, destWardId, weight, apiKey);
            var result = await _feeCalculationService.CalculateOrderFeeAsync(request);

            if (result.Result == Result.Success)
            {
                orderFin.UpdateFromCalculationResult(result);
            }

            return result;
        }

        /// <summary>
        /// Tính toán cước cho đơn hàng mới từ thông tin cơ bản
        /// </summary>
        /// <param name="customerId">ID khách hàng</param>
        /// <param name="sourceWardId">ID phường/xã nguồn</param>
        /// <param name="destWardId">ID phường/xã đích</param>
        /// <param name="weight">Trọng lượng (gram)</param>
        /// <param name="collectAmount">Tiền thu hộ</param>
        /// <param name="payFeeType">Loại thanh toán</param>
        /// <param name="pickupSubFee">Phụ phí lấy hàng</param>
        /// <param name="deliverySubFee">Phụ phí giao hàng</param>
        /// <param name="insuranceFee">Phí bảo hiểm</param>
        /// <param name="discount">Giảm giá</param>
        /// <param name="sourceFee">Cước người gửi trả (cho SplitPay)</param>
        /// <param name="apiKey">API key</param>
        /// <returns>Kết quả tính toán</returns>
        public async Task<OrderFeeCalculationResult> CalculateOrderFeeAsync(
            int customerId,
            int sourceWardId,
            int destWardId,
            decimal weight,
            decimal collectAmount = 0,
            PayFeeType payFeeType = PayFeeType.ConsigneePay,
            decimal pickupSubFee = 0,
            decimal deliverySubFee = 0,
            decimal insuranceFee = 0,
            decimal discount = 0,
            decimal sourceFee = 0,
            string apiKey = "")
        {
            var request = new OrderFeeCalculationRequest
            {
                CustomerId = customerId,
                SourceWardId = sourceWardId,
                DestWardId = destWardId,
                Weight = weight,
                CollectAmount = collectAmount,
                PickupSubFee = pickupSubFee,
                DeliverySubFee = deliverySubFee,
                InsuranceFee = insuranceFee,
                ReturnFee = 0,
                Discount = discount,
                PayFeeType = payFeeType,
                SourceFee = sourceFee,
                ApiKey = apiKey
            };

            return await _feeCalculationService.CalculateOrderFeeAsync(request);
        }

        /// <summary>
        /// Tính lại cước khi cập nhật sản phẩm
        /// </summary>
        /// <param name="orderFin">OrderFin entity</param>
        /// <param name="newWeight">Trọng lượng mới (gram)</param>
        /// <param name="customerId">ID khách hàng</param>
        /// <param name="sourceWardId">ID phường/xã nguồn</param>
        /// <param name="destWardId">ID phường/xã đích</param>
        /// <param name="apiKey">API key</param>
        /// <returns>Kết quả tính toán</returns>
        public async Task<OrderFeeCalculationResult> RecalculateFeeForPackageUpdateAsync(
            OrderFin orderFin,
            decimal newWeight,
            int customerId,
            int sourceWardId,
            int destWardId,
            string apiKey = "")
        {
            var request = orderFin.ToCalculationRequest(customerId, sourceWardId, destWardId, newWeight, apiKey);
            var result = await _feeCalculationService.CalculateOrderFeeAsync(request);

            if (result.Result == Result.Success)
            {
                orderFin.UpdateFromCalculationResult(result);
            }

            return result;
        }

        /// <summary>
        /// Tính lại cước khi cập nhật địa chỉ
        /// </summary>
        /// <param name="orderFin">OrderFin entity</param>
        /// <param name="customerId">ID khách hàng</param>
        /// <param name="newSourceWardId">ID phường/xã nguồn mới</param>
        /// <param name="newDestWardId">ID phường/xã đích mới</param>
        /// <param name="weight">Trọng lượng (gram)</param>
        /// <param name="apiKey">API key</param>
        /// <returns>Kết quả tính toán</returns>
        public async Task<OrderFeeCalculationResult> RecalculateFeeForAddressUpdateAsync(
            OrderFin orderFin,
            int customerId,
            int newSourceWardId,
            int newDestWardId,
            decimal weight,
            string apiKey = "")
        {
            var request = orderFin.ToCalculationRequest(customerId, newSourceWardId, newDestWardId, weight, apiKey);
            var result = await _feeCalculationService.CalculateOrderFeeAsync(request);

            if (result.Result == Result.Success)
            {
                orderFin.UpdateFromCalculationResult(result);
            }

            return result;
        }

        /// <summary>
        /// Chỉ tính phí VAT mà không tính lại toàn bộ
        /// </summary>
        /// <param name="totalFeeAfterVat">Tổng cước đã bao gồm VAT</param>
        /// <returns>Phí VAT</returns>
        public decimal CalculateVatFeeOnly(decimal totalFeeAfterVat)
        {
            return _feeCalculationService.CalculateVatFee(totalFeeAfterVat);
        }

        /// <summary>
        /// Phân bổ lại cước theo loại thanh toán mới
        /// </summary>
        /// <param name="orderFin">OrderFin entity</param>
        /// <param name="newPayFeeType">Loại thanh toán mới</param>
        /// <param name="newSourceFee">Cước người gửi trả mới (cho SplitPay)</param>
        public void ReallocateFeeByPaymentType(OrderFin orderFin, PayFeeType newPayFeeType, decimal newSourceFee = 0)
        {
            orderFin.PayFeeType = newPayFeeType;

            var allocation = _feeCalculationService.AllocateFeeByPaymentType(
                orderFin.TotalFeeAfterVat,
                newPayFeeType,
                newSourceFee);

            orderFin.SourceFee = allocation.SourceFee;
            orderFin.DestFee = allocation.DestFee;
            orderFin.TransferFee = allocation.TransferFee;
            orderFin.DeductCodFee = allocation.DeductCodFee;
        }
    }
}
