namespace ZB.MOM.WW.Auth.ApiKeys.Sqlite;

/// <summary>
/// Schema constants and table DDL for the API-key SQLite store.
/// </summary>
public static class SqliteAuthSchema
{
    /// <summary>
    /// The schema version this build creates and supports. Versions <c>1</c> and <c>2</c> shared a
    /// byte-identical schema (the store was extracted from the donor MxAccessGateway, whose deployed
    /// <c>gateway-auth.db</c> stamps <c>version = 2</c>); <c>3</c> adds the nullable
    /// <c>expires_utc</c> column (API-key expiry, archreview G-2). The migration is additive and
    /// backward-compatible: an existing v1/v2 database is upgraded in place (the column is added via
    /// an idempotent <c>ALTER TABLE</c>, existing rows get <c>NULL</c> = never-expires) and re-stamped
    /// to 3, so no key is invalidated on upgrade. The migrator still only refuses an on-disk version
    /// <em>newer</em> than this, so a donor v2 database is accepted (2 &lt;= 3) and upgraded.
    /// </summary>
    public const int CurrentVersion = 3;

    /// <summary>Name of the single-row table tracking the applied schema version.</summary>
    public const string SchemaVersionTable = "schema_version";

    /// <summary>Name of the table storing API-key records.</summary>
    public const string ApiKeysTable = "api_keys";

    /// <summary>Name of the append-only audit table.</summary>
    public const string ApiKeyAuditTable = "api_key_audit";

    /// <summary>DDL creating the single-row schema-version table.</summary>
    public const string CreateSchemaVersionTable = """
        CREATE TABLE IF NOT EXISTS schema_version (
            id INTEGER PRIMARY KEY CHECK (id = 1),
            version INTEGER NOT NULL,
            applied_utc TEXT NOT NULL
        );
        """;

    /// <summary>DDL creating the API-key record table.</summary>
    /// <remarks>
    /// <c>expires_utc</c> (nullable) was added at schema v3. Fresh databases get it from this DDL;
    /// existing v1/v2 databases get it via the idempotent <c>ALTER TABLE</c> in
    /// <see cref="SqliteAuthStoreMigrator"/> (<see cref="AddExpiresUtcColumn"/>).
    /// </remarks>
    public const string CreateApiKeysTable = """
        CREATE TABLE IF NOT EXISTS api_keys (
            key_id TEXT PRIMARY KEY,
            key_prefix TEXT NOT NULL,
            secret_hash BLOB NOT NULL,
            display_name TEXT NOT NULL,
            scopes TEXT NOT NULL,
            constraints TEXT NULL,
            created_utc TEXT NOT NULL,
            last_used_utc TEXT NULL,
            revoked_utc TEXT NULL,
            expires_utc TEXT NULL
        );
        """;

    /// <summary>Name of the nullable expiry column added at schema v3.</summary>
    public const string ExpiresUtcColumn = "expires_utc";

    /// <summary>
    /// Idempotent forward migration adding <see cref="ExpiresUtcColumn"/> to a pre-v3
    /// <c>api_keys</c> table. Guarded by a column-existence check at the call site, so it is safe to
    /// run against a fresh (already-has-the-column) database too.
    /// </summary>
    public const string AddExpiresUtcColumn =
        "ALTER TABLE api_keys ADD COLUMN expires_utc TEXT NULL;";

    /// <summary>DDL creating the append-only audit table.</summary>
    public const string CreateApiKeyAuditTable = """
        CREATE TABLE IF NOT EXISTS api_key_audit (
            audit_id INTEGER PRIMARY KEY AUTOINCREMENT,
            key_id TEXT NULL,
            event_type TEXT NOT NULL,
            remote_address TEXT NULL,
            created_utc TEXT NOT NULL,
            details TEXT NULL
        );
        """;

    /// <summary>DDL creating supporting indexes (idempotent).</summary>
    public const string CreateIndexes = """
        CREATE INDEX IF NOT EXISTS ix_api_keys_revoked_utc
            ON api_keys (revoked_utc);

        CREATE INDEX IF NOT EXISTS ix_api_key_audit_key_id_created_utc
            ON api_key_audit (key_id, created_utc);
        """;
}
