using Xunit;

namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations;

/// <summary>
/// Content guard for the <c>FixAuditPurgerRoleGrants</c> migration (arch-review 04, S3).
/// The switch-out dance CREATEs a staging table and the per-channel override runs a bounded
/// row DELETE — but the shipped <c>scadabridge_audit_purger</c> role only carried
/// <c>SELECT</c> + <c>ALTER ON SCHEMA::dbo</c>, which does NOT confer the database-level
/// <c>CREATE TABLE</c> permission nor row-level <c>DELETE</c>. This test asserts the migration
/// source grants both, so a segregated maintenance principal can genuinely execute the purge.
/// A pure source-content scan (no MSSQL required) — the schema-application sanity check lives
/// in the MSSQL migration suite.
/// </summary>
public class FixAuditPurgerRoleGrantsTests
{
    private static string ReadMigrationSource()
    {
        var migrationsDir = Path.Combine(
            GetConfigurationDatabaseSourceDirectory(), "Migrations");

        // Timestamp-prefixed filename; match the non-Designer partial only.
        var file = Directory.GetFiles(migrationsDir, "*_FixAuditPurgerRoleGrants.cs")
            .FirstOrDefault(f => !f.EndsWith(".Designer.cs", StringComparison.OrdinalIgnoreCase));

        Assert.True(file is not null,
            "Expected a *_FixAuditPurgerRoleGrants.cs migration under " + migrationsDir +
            " — scaffold it with `dotnet ef migrations add FixAuditPurgerRoleGrants` (build first, NO --no-build).");
        return File.ReadAllText(file!);
    }

    [Fact]
    public void Migration_Grants_CreateTable_To_Purger()
    {
        var src = ReadMigrationSource();
        Assert.Contains("GRANT CREATE TABLE TO scadabridge_audit_purger", src);
    }

    [Fact]
    public void Migration_Grants_Delete_On_AuditLog_To_Purger()
    {
        var src = ReadMigrationSource();
        Assert.Contains("GRANT DELETE ON dbo.AuditLog TO scadabridge_audit_purger", src);
    }

    [Fact]
    public void Down_Revokes_Both_Grants()
    {
        var src = ReadMigrationSource();
        // Down must reverse both grants so the migration is cleanly reversible.
        Assert.Contains("REVOKE CREATE TABLE", src);
        Assert.Contains("REVOKE DELETE ON dbo.AuditLog", src);
    }

    // Same walk-up anchor pattern the append-only guard uses.
    private static string GetConfigurationDatabaseSourceDirectory()
    {
        var dir = new DirectoryInfo(AppContext.BaseDirectory);
        while (dir != null)
        {
            var candidate = Path.Combine(
                dir.FullName, "src",
                "ZB.MOM.WW.ScadaBridge.ConfigurationDatabase",
                "ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.csproj");
            if (File.Exists(candidate))
            {
                return Path.GetDirectoryName(candidate)!;
            }
            dir = dir.Parent;
        }
        throw new InvalidOperationException(
            "Could not locate ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.csproj by walking up from the test output directory.");
    }
}
