using Microsoft.Extensions.Configuration;
using Tiku.Api.Options;
using Tiku.Application.Security;
using Tiku.Infrastructure.Commerce;

namespace Tiku.IntegrationTests.Api;

public sealed class ProductionConfigurationTests
{
    [Fact]
    public void Database_connection_is_required_outside_development()
    {
        var configuration = new ConfigurationBuilder().Build();

        var exception = Assert.Throws<InvalidOperationException>(() =>
            OptionsValidation.ResolveDatabaseConnectionString(configuration, isDevelopment: false));

        Assert.Contains("Database connection is required", exception.Message, StringComparison.Ordinal);
    }

    [Fact]
    public void Development_database_default_uses_current_system_user_without_a_password()
    {
        var configuration = new ConfigurationBuilder().Build();

        var connectionString = OptionsValidation.ResolveDatabaseConnectionString(
            configuration,
            isDevelopment: true);

        Assert.Contains($"Username={Environment.UserName}", connectionString, StringComparison.Ordinal);
        Assert.DoesNotContain("Password=", connectionString, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public void Production_requires_an_explicit_rsa_private_key()
    {
        var options = new JwtOptions
        {
            KeyId = "production-key",
            PrivateKeyPem = string.Empty
        };

        Assert.False(OptionsValidation.BeValidJwtOptions(options, isProduction: true));
        Assert.True(OptionsValidation.BeValidJwtOptions(options, isProduction: false));

        options.PrivateKeyPem = TestJwtKeys.PrivateKeyPem;
        Assert.True(OptionsValidation.BeValidJwtOptions(options, isProduction: true));
    }

    [Fact]
    public void Jwt_configuration_rejects_development_kid_malformed_keys_and_current_kid_in_old_key_set()
    {
        var options = new JwtOptions
        {
            KeyId = "development-ephemeral",
            PrivateKeyPem = TestJwtKeys.PrivateKeyPem
        };
        Assert.False(OptionsValidation.BeValidJwtOptions(options, isProduction: true));

        options.KeyId = "current-key";
        options.PrivateKeyPem = "-----BEGIN PRIVATE KEY-----\ninvalid\n-----END PRIVATE KEY-----";
        Assert.False(OptionsValidation.BeValidJwtOptions(options, isProduction: false));

        options.PrivateKeyPem = TestJwtKeys.PrivateKeyPem;
        options.PublicKeys[options.KeyId] = TestJwtKeys.PublicKeyPem;
        Assert.False(OptionsValidation.BeValidJwtOptions(options, isProduction: false));

        options.PublicKeys.Clear();
        options.PublicKeys["old-key"] = TestJwtKeys.PublicKeyPem;
        Assert.True(OptionsValidation.BeValidJwtOptions(options, isProduction: true));
    }

    [Fact]
    public void Tenant_secret_encryption_requires_a_32_byte_base64_key()
    {
        Assert.False(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions()));
        Assert.False(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions
        {
            KeyId = "key-v1",
            MasterKey = Convert.ToBase64String(new byte[16])
        }));
        Assert.True(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions
        {
            KeyId = "key-v1",
            MasterKey = Convert.ToBase64String(new byte[32])
        }));
    }

    [Fact]
    public void Production_network_configuration_requires_formal_hosts_allowed_hosts_and_proxy()
    {
        var developmentDefaults = new TenantResolutionOptions();
        var wildcard = new ConfigurationBuilder()
            .AddInMemoryCollection(new Dictionary<string, string?> { ["AllowedHosts"] = "*" })
            .Build();
        Assert.False(OptionsValidation.BeValidTenantResolutionOptions(developmentDefaults, wildcard, true));

        var production = new TenantResolutionOptions
        {
            PlatformHosts = ["admin.example.com"],
            TrustedProxyAddresses = ["10.0.0.10"]
        };
        var explicitHosts = new ConfigurationBuilder()
            .AddInMemoryCollection(new Dictionary<string, string?> { ["AllowedHosts"] = "admin.example.com;api.example.com" })
            .Build();
        Assert.True(OptionsValidation.BeValidTenantResolutionOptions(production, explicitHosts, true));
    }
}
