using SIGCM2.Application.Abstractions.Persistence;

namespace SIGCM2.Application.Pricing.ChargeableChars;

/// <summary>
/// PRC-001 — Implements IChargeableCharConfigService.
/// Delegates to IChargeableCharConfigRepository.GetActiveForProductTypeAsync, then applies
/// the per-ProductType > global priority rule in memory.
///
/// Priority rule: if the same Symbol appears as both global (ProductTypeId IS NULL) and
/// per-ProductType, the per-ProductType row wins. The SP returns both; we resolve in Application.
/// </summary>
public sealed class ChargeableCharConfigService : IChargeableCharConfigService
{
    private readonly IChargeableCharConfigRepository _repo;

    public ChargeableCharConfigService(IChargeableCharConfigRepository repo)
    {
        _repo = repo;
    }

    /// <inheritdoc />
    public async Task<IReadOnlyDictionary<string, ChargeableCharSnapshot>> GetActiveConfigForProductTypeAsync(
        long productTypeId,
        DateOnly asOf,
        CancellationToken ct = default)
    {
        var allRows = await _repo.GetActiveForProductTypeAsync(productTypeId, asOf, ct);

        // Build a dictionary keyed by Symbol.
        // Per-ProductType rows (ProductTypeId != null) take priority over global rows (ProductTypeId == null).
        var result = new Dictionary<string, ChargeableCharSnapshot>(StringComparer.Ordinal);

        // Two-pass: first add global rows, then overwrite with per-ProductType rows.
        foreach (var row in allRows.Where(r => r.ProductTypeId is null))
            result[row.Symbol] = new ChargeableCharSnapshot(row.Category, row.PricePerUnit);

        foreach (var row in allRows.Where(r => r.ProductTypeId is not null))
            result[row.Symbol] = new ChargeableCharSnapshot(row.Category, row.PricePerUnit);

        return result;
    }
}
