#nullable enable
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Baya.Application.Contracts.Common;
using Microsoft.Extensions.Options;

namespace Baya.Infrastructure.CrossCutting.Seams;

/// <summary>
/// Mock <see cref="IIdentityKycProvider"/>: a deterministic fake identity + liveness check — no real
/// OCR/liveness call. Passes every well-formed national id except the configured
/// <see cref="IdentityKycOptions.FailNationalId"/>. On pass it reports a matched name and populates the
/// verified identity. A real Iranian e-KYC vendor (Finnotech / U-ID / Jibbit / Farashensa / Verify /
/// Kavoshak) swaps in by a registration change — callers are unchanged.
/// </summary>
public sealed class MockIdentityKycProvider(IOptions<SeamOptions> options) : IIdentityKycProvider
{
    private readonly IdentityKycOptions _options = options.Value.IdentityKyc;

    public Task<IdentityKycResult> VerifyAsync(string nationalId, string? livenessPayload, CancellationToken cancellationToken = default)
    {
        var id = (nationalId ?? string.Empty).Trim();
        var vendorRef = $"MOCK-KYC-{Token(id)}";
        var wellFormed = id.Length == 10 && id.All(char.IsDigit);

        if (!wellFormed || string.Equals(id, _options.FailNationalId, StringComparison.Ordinal))
        {
            return Task.FromResult(new IdentityKycResult(
                Passed: false,
                MatchedName: null,
                VendorRef: vendorRef,
                ExternalResponseJson: Payload("fail", id, livenessPayload, passed: false),
                FailureReason: "Identity could not be verified against the civil registry."));
        }

        return Task.FromResult(new IdentityKycResult(
            Passed: true,
            MatchedName: _options.MatchedName,
            VendorRef: vendorRef,
            ExternalResponseJson: Payload("pass", id, livenessPayload, passed: true),
            FailureReason: null));
    }

    private static string Payload(string outcome, string nationalId, string? liveness, bool passed)
        => JsonSerializer.Serialize(new
        {
            provider = "mock_identity_kyc",
            outcome,
            passed,
            national_id_present = !string.IsNullOrEmpty(nationalId),
            liveness_present = !string.IsNullOrEmpty(liveness)
        });

    private static string Token(string value)
        => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value)))[..12];
}
