#nullable enable
using System.Text.Json;
using Baya.Application.Contracts.Common;

namespace Baya.Infrastructure.CrossCutting.Seams.Real;

/// <summary>
/// Real <see cref="IBankAccountOwnershipVerifier"/> over the Finnotech استعلام شبا owner ↔ national-id inquiry
/// (refinement-phase-8, 5.3 — the b13 first-payout money-mule gate). Selected by
/// <c>Seams:BankOwnership:Provider = finnotech</c>. Resolves the IBAN's registered owner and matches it against
/// the nurse's national id; persists the vendor track id.
/// </summary>
public sealed class FinnotechBankAccountOwnershipVerifier(FinnotechClient client) : IBankAccountOwnershipVerifier
{
    public async Task<OwnershipInquiryResult> VerifyOwnershipAsync(string iban, string? nurseNationalId, CancellationToken cancellationToken = default)
    {
        var trackId = FinnotechClient.NewTrackId();
        var vendorRef = $"FINNOTECH-SHEBA-{trackId}";
        var path = $"oak/v2/clients/{client.ClientId}/ibanToNid" +
                   $"?iban={Uri.EscapeDataString(Normalize(iban))}&trackId={trackId}";

        var (document, _) = await client.GetAsync(path, cancellationToken);
        using var _doc = document;

        var root = document.RootElement;
        string ownerName = string.Empty;
        string? ownerNid = null;

        if (root.TryGetProperty("result", out var result))
        {
            if (result.TryGetProperty("name", out var name) && name.ValueKind == JsonValueKind.String)
                ownerName = name.GetString() ?? string.Empty;
            if (result.TryGetProperty("nationalCode", out var nid) && nid.ValueKind == JsonValueKind.String)
                ownerNid = nid.GetString();
        }

        // Ownership matches when the account's registered national code equals the nurse's. If the vendor did not
        // return a national code we cannot assert a match — fail closed (matched = false), since this is the gate.
        var matched = !string.IsNullOrEmpty(ownerNid)
                      && !string.IsNullOrEmpty(nurseNationalId)
                      && string.Equals(ownerNid, nurseNationalId, StringComparison.Ordinal);

        return new OwnershipInquiryResult(matched, ownerName, vendorRef);
    }

    private static string Normalize(string iban)
        => string.IsNullOrEmpty(iban) ? string.Empty : iban.Replace(" ", string.Empty).ToUpperInvariant();
}
