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

namespace Lada.Framework.Infrastructures.Extensions
{
    /// <summary>
    /// Extension methods cho OrderFeeCalculationService
    /// </summary>
    public static class OrderFeeCalculationExtensions
    {
        /// <summary>
        /// Đăng ký OrderFeeCalculationService vào DI container
        /// </summary>
        /// <param name="services">Service collection</param>
        /// <returns>Service collection</returns>
        public static IServiceCollection AddOrderFeeCalculationService(this IServiceCollection services)
        {
            services.AddTransient<IOrderFeeCalculationService, OrderFeeCalculationService>();
            return services;
        }

        /// <summary>
        /// Chuyển đổi từ OrderFin entity sang OrderFeeCalculationRequest
        /// </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>OrderFeeCalculationRequest</returns>
        public static OrderFeeCalculationRequest ToCalculationRequest(
            this OrderFin orderFin,
            int customerId,
            int sourceWardId,
            int destWardId,
            decimal weight,
            string apiKey = "")
        {
            return new OrderFeeCalculationRequest
            {
                CustomerId = customerId,
                SourceWardId = sourceWardId,
                DestWardId = destWardId,
                Weight = weight,
                CollectAmount = orderFin.CollectAmount,
                PickupSubFee = orderFin.PickupSubFee,
                DeliverySubFee = orderFin.DeliverySubFee,
                InsuranceFee = orderFin.InsuranceFee,
                ReturnFee = orderFin.ReturnFee,
                Discount = orderFin.Discount,
                PayFeeType = orderFin.PayFeeType,
                SourceFee = orderFin.SourceFee,
                ApiKey = apiKey
            };
        }

        /// <summary>
        /// Cập nhật OrderFin từ kết quả tính toán cước
        /// </summary>
        /// <param name="orderFin">OrderFin entity</param>
        /// <param name="calculationResult">Kết quả tính toán cước</param>
        public static void UpdateFromCalculationResult(this OrderFin orderFin, OrderFeeCalculationResult calculationResult)
        {
            if (calculationResult.Result != Result.Success)
                return;

            orderFin.Fee = calculationResult.BaseFee;
            orderFin.CodFee = calculationResult.CodFee;
            orderFin.PickupSubFee = calculationResult.PickupSubFee;
            orderFin.DeliverySubFee = calculationResult.DeliverySubFee;
            orderFin.InsuranceFee = calculationResult.InsuranceFee;
            orderFin.ReturnFee = calculationResult.ReturnFee;
            orderFin.Discount = calculationResult.Discount;
            orderFin.VatFee = calculationResult.VatFee;
            orderFin.SourceFee = calculationResult.SourceFee;
            orderFin.DestFee = calculationResult.DestFee;
            orderFin.TransferFee = calculationResult.TransferFee;
            orderFin.DeductCodFee = calculationResult.DeductCodFee;
        }

        /// <summary>
        /// Tạo OrderFeeCalculationRequest 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="apiKey">API key</param>
        /// <returns>OrderFeeCalculationRequest</returns>
        public static OrderFeeCalculationRequest CreateCalculationRequest(
            int customerId,
            int sourceWardId,
            int destWardId,
            decimal weight,
            decimal collectAmount = 0,
            PayFeeType payFeeType = PayFeeType.ConsigneePay,
            string apiKey = "")
        {
            return new OrderFeeCalculationRequest
            {
                CustomerId = customerId,
                SourceWardId = sourceWardId,
                DestWardId = destWardId,
                Weight = weight,
                CollectAmount = collectAmount,
                PickupSubFee = 0,
                DeliverySubFee = 0,
                InsuranceFee = 0,
                ReturnFee = 0,
                Discount = 0,
                PayFeeType = payFeeType,
                SourceFee = 0,
                ApiKey = apiKey
            };
        }

        /// <summary>
        /// Kiểm tra xem có cần tính lại cước không
        /// </summary>
        /// <param name="oldRequest">Request cũ</param>
        /// <param name="newRequest">Request mới</param>
        /// <returns>True nếu cần tính lại</returns>
        public static bool ShouldRecalculateFee(this OrderFeeCalculationRequest oldRequest, OrderFeeCalculationRequest newRequest)
        {
            return oldRequest.CustomerId != newRequest.CustomerId ||
                   oldRequest.SourceWardId != newRequest.SourceWardId ||
                   oldRequest.DestWardId != newRequest.DestWardId ||
                   oldRequest.Weight != newRequest.Weight ||
                   oldRequest.CollectAmount != newRequest.CollectAmount ||
                   oldRequest.PickupSubFee != newRequest.PickupSubFee ||
                   oldRequest.DeliverySubFee != newRequest.DeliverySubFee ||
                   oldRequest.InsuranceFee != newRequest.InsuranceFee ||
                   oldRequest.ReturnFee != newRequest.ReturnFee ||
                   oldRequest.Discount != newRequest.Discount ||
                   oldRequest.PayFeeType != newRequest.PayFeeType ||
                   oldRequest.SourceFee != newRequest.SourceFee;
        }
    }
}
