using Meezi.API.Configuration;
using Meezi.Core.Delivery;
using Meezi.Core.Enums;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace Meezi.API.Services.Delivery;

public interface ICommissionCalculator
{
    Task<decimal> ResolveRatePercentAsync(string cafeId, DeliveryPlatform platform, CancellationToken ct = default);
    decimal CalculateCommission(decimal grossTotal, decimal ratePercent);
    Task<decimal> CalculateForOrderAsync(
        string cafeId,
        UnifiedDeliveryOrder order,
        CancellationToken ct = default);
}

public class CommissionCalculator : ICommissionCalculator
{
    private readonly AppDbContext _db;
    private readonly DeliveryPlatformsOptions _options;

    public CommissionCalculator(AppDbContext db, IOptions<DeliveryPlatformsOptions> options)
    {
        _db = db;
        _options = options.Value;
    }

    public async Task<decimal> ResolveRatePercentAsync(
        string cafeId,
        DeliveryPlatform platform,
        CancellationToken ct = default)
    {
        var custom = await _db.DeliveryCommissionRates
            .Where(r => r.CafeId == cafeId && r.Platform == platform && r.IsActive)
            .Select(r => (decimal?)r.RatePercent)
            .FirstOrDefaultAsync(ct);

        if (custom is > 0)
            return custom.Value;

        return platform switch
        {
            DeliveryPlatform.Snappfood => _options.DefaultSnappfoodCommissionPercent,
            DeliveryPlatform.Tap30 => _options.DefaultTap30CommissionPercent,
            DeliveryPlatform.Digikala => _options.DefaultDigikalaCommissionPercent,
            _ => 0m
        };
    }

    public decimal CalculateCommission(decimal grossTotal, decimal ratePercent) =>
        grossTotal <= 0 || ratePercent <= 0
            ? 0m
            : Math.Round(grossTotal * ratePercent / 100m, 0);

    public async Task<decimal> CalculateForOrderAsync(
        string cafeId,
        UnifiedDeliveryOrder order,
        CancellationToken ct = default)
    {
        if (order.Payment.Commission is decimal fromPlatform)
            return fromPlatform;

        var rate = await ResolveRatePercentAsync(cafeId, order.Platform, ct);
        var gross = order.Payment.Total > 0
            ? order.Payment.Total
            : order.Items.Sum(i => i.UnitPrice * i.Quantity);
        return CalculateCommission(gross, rate);
    }
}
