using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Commerce;
using Tiku.Application.Tenancy;
using Tiku.Domain.Tenancy;
using Tiku.Domain.Commerce;
using Tiku.Infrastructure.Persistence;

namespace Tiku.Infrastructure.Commerce;

internal sealed class PaymentProviderConfigService(
    ITenantExternalProviderConfigService providerConfigService) : IPaymentProviderConfigService
{
    public async Task<PaymentProviderAccount> GetActiveAccountAsync(
        Guid tenantId,
        string provider,
        CancellationToken cancellationToken = default)
    {
        TenantExternalProviderAccount account;
        try
        {
            account = await providerConfigService.GetActiveProviderAsync(
                tenantId,
                TenantExternalProviderCapability.Payment,
                NormalizeProvider(provider),
                cancellationToken);
        }
        catch (TenantExternalProviderException exception)
        {
            throw new PaymentProviderException(exception.Message, "payment_provider_not_configured");
        }

        return new PaymentProviderAccount(
            account.TenantId,
            account.Provider,
            GetString(account.ConfigPublic, "mode") ?? "TenantCollect",
            account.ConfigPublic,
            account.SecretPayload);
    }

    private static string NormalizeProvider(string provider)
    {
        var normalized = provider.Trim().ToLowerInvariant().Replace("-", "_", StringComparison.Ordinal);

        return normalized switch
        {
            "wechat" or "wechatpay" or "wxpay" or "wx_pay" => PaymentProviders.WechatPay,
            "ali_pay" => PaymentProviders.Alipay,
            "" => throw new PaymentProviderException("Payment provider is required.", "payment_provider_required"),
            _ => normalized
        };
    }

    private static string? GetString(JsonElement element, params string[] keys)
    {
        if (element.ValueKind != JsonValueKind.Object)
        {
            return null;
        }

        foreach (var key in keys)
        {
            if (element.TryGetProperty(key, out var property) &&
                property.ValueKind == JsonValueKind.String)
            {
                return property.GetString();
            }
        }

        return null;
    }
}
