using Baya.Web.Api.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;

namespace Baya.Test.Api;

/// <summary>
/// Refinement Phase 5 — proves the fail-fast secret guard: a deployed environment left on committed
/// placeholders refuses to boot with a clear message, and boots once real values are supplied. (The
/// integration host runs as "Testing", where the guard is intentionally skipped, so this exercises it
/// directly.)
/// </summary>
public class StartupSecretsGuardTests
{
    private static WebApplicationBuilder ProductionBuilder(Dictionary<string, string?> settings)
    {
        var builder = WebApplication.CreateBuilder(new WebApplicationOptions { EnvironmentName = "Production" });
        builder.Configuration.AddInMemoryCollection(settings);
        return builder;
    }

    private static Dictionary<string, string?> RealSecrets() => new()
    {
        ["ConnectionStrings:SqlServer"] = "Server=db;Database=Baya;User Id=app;Password=real-value;",
        ["ConnectionStrings:logDb"] = "Server=db;Database=Baya_Logs;User Id=app;Password=real-value;",
        ["IdentitySettings:SecretKey"] = "a-real-production-jwe-signing-key-0123456789",
        ["IdentitySettings:Encryptkey"] = "real-16-byte-key",
        ["Seams:FieldEncryption:Key"] = "a-real-production-field-key",
        ["Seams:FieldEncryption:HashKey"] = "a-real-production-hash-key"
    };

    [Fact]
    public void PlaceholderConnectionString_InDeployedEnvironment_RefusesToStart()
    {
        var settings = RealSecrets();
        settings["ConnectionStrings:SqlServer"] = "Server=localhost;Password=SET_VIA_USER_SECRETS_OR_ENV;";

        var ex = Assert.Throws<InvalidOperationException>(() => ProductionBuilder(settings).ValidateRequiredSecrets());
        Assert.Contains("ConnectionStrings:SqlServer", ex.Message);
    }

    [Fact]
    public void PlaceholderJweKey_InDeployedEnvironment_RefusesToStart()
    {
        var settings = RealSecrets();
        settings["IdentitySettings:SecretKey"] = "SET_VIA_USER_SECRETS_OR_ENV";

        var ex = Assert.Throws<InvalidOperationException>(() => ProductionBuilder(settings).ValidateRequiredSecrets());
        Assert.Contains("IdentitySettings:SecretKey", ex.Message);
    }

    [Fact]
    public void DevOnlyKeyLeakedToDeployedEnvironment_RefusesToStart()
    {
        var settings = RealSecrets();
        settings["Seams:FieldEncryption:Key"] = "local-dev-field-encryption-key-not-for-production";

        Assert.Throws<InvalidOperationException>(() => ProductionBuilder(settings).ValidateRequiredSecrets());
    }

    [Fact]
    public void RealSecrets_InDeployedEnvironment_StartUpSucceeds()
    {
        var exception = Record.Exception(() => ProductionBuilder(RealSecrets()).ValidateRequiredSecrets());
        Assert.Null(exception);
    }
}
