#nullable enable
using System.Net.Http.Json;
using System.Text.Json;
using Baya.Application.Contracts.Payments;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Baya.Infrastructure.CrossCutting.Seams.Real;

/// <summary>
/// Real <see cref="ISettlementSplitProvider"/> — the تسهیم (settlement-sharing) rail (refinement-phase-8, 6.1).
/// Selected by <c>Seams:Payments:Provider</c> together with the PSP + webhook adapters. Registers a split-by-ratio
/// to the beneficiaries' <b>registered IBANs</b> (nurse payout + platform commission); the acquirer credits each
/// IBAN directly — <b>the platform never custodies funds</b>, the ledger only mirrors what legally sits at the
/// provider/bank. Amounts are IRR <c>long</c>.
///
/// <para>The exact تسهیم endpoint/payload is acquirer-specific (ZarinPal/Zibal/Vandar each differ) and honours the
/// ~100,000 IRR per-leg minimum; the request shape here is the common split-list form. A deployment confirms the
/// concrete route + credential source (the platform SHEBA from <c>Seams:Payments:PlatformSheba</c>, each nurse
/// SHEBA from the b3 <c>matched_national_id</c>-gated bank account) at integration.</para>
/// </summary>
public sealed class ProviderSettlementSplitProvider(
    HttpClient httpClient,
    IOptions<SeamOptions> options,
    ILogger<ProviderSettlementSplitProvider> logger) : ISettlementSplitProvider
{
    private readonly PaymentsOptions _options = options.Value.Payments;

    private string BaseUrl => _options.BaseUrl.TrimEnd('/');

    public async ValueTask<SettlementResult> RegisterSplitAsync(long bookingId, IReadOnlyList<SettlementLeg> legs, CancellationToken cancellationToken = default)
    {
        if (legs.Count == 0 || legs.Sum(l => l.AmountIrr) <= 0)
            return new SettlementResult(SettlementStatus.Failed);

        var payload = new
        {
            booking_id = bookingId,
            wages = legs.Select(l => new { iban = l.Sheba, amount = l.AmountIrr, description = l.Beneficiary }),
        };

        try
        {
            using var response = await httpClient.PostAsJsonAsync($"{BaseUrl}/settlement/split", payload, cancellationToken);
            response.EnsureSuccessStatusCode();
            return new SettlementResult(SettlementStatus.Registered);
        }
        catch (HttpRequestException ex)
        {
            logger.LogWarning(ex, "تسهیم split registration failed for booking {BookingId}", bookingId);
            return new SettlementResult(SettlementStatus.Failed);
        }
    }

    public async ValueTask<SettlementResult> GetSplitStatusAsync(long bookingId, CancellationToken cancellationToken = default)
    {
        try
        {
            using var response = await httpClient.GetAsync($"{BaseUrl}/settlement/split/{bookingId}", cancellationToken);
            response.EnsureSuccessStatusCode();
            var raw = await response.Content.ReadAsStringAsync(cancellationToken);

            using var doc = JsonDocument.Parse(raw);
            var status = doc.RootElement.TryGetProperty("status", out var s) ? s.GetString() : null;
            return new SettlementResult(status?.ToLowerInvariant() switch
            {
                "settled" or "done" or "paid" => SettlementStatus.Settled,
                "failed" or "rejected" => SettlementStatus.Failed,
                _ => SettlementStatus.Registered,
            });
        }
        catch (HttpRequestException ex)
        {
            logger.LogWarning(ex, "تسهیم split status read failed for booking {BookingId}", bookingId);
            return new SettlementResult(SettlementStatus.Registered);
        }
    }
}
