"""v39 → v40 migration: add params_before, client_ip, client_kind,
correlation_id columns to audit_log + three indices."""
import duckdb
from src.db import _ensure_schema as init_database, SCHEMA_VERSION


def test_schema_version_includes_v40():
    assert SCHEMA_VERSION >= 40


def test_v40_columns_exist_after_init(tmp_path):
    db_path = tmp_path / "test.duckdb"
    conn = duckdb.connect(str(db_path))
    init_database(conn)
    cols = {row[1] for row in conn.execute("PRAGMA table_info(audit_log)").fetchall()}
    assert "params_before" in cols
    assert "client_ip" in cols
    assert "client_kind" in cols
    assert "correlation_id" in cols
    conn.close()


def test_v40_indices_exist(tmp_path):
    db_path = tmp_path / "test.duckdb"
    conn = duckdb.connect(str(db_path))
    init_database(conn)
    idx_names = {row[0] for row in conn.execute(
        "SELECT index_name FROM duckdb_indexes WHERE table_name='audit_log'"
    ).fetchall()}
    assert "idx_audit_timestamp_desc" in idx_names
    assert "idx_audit_user_time" in idx_names
    assert "idx_audit_action_time" in idx_names
    conn.close()


def test_v39_to_v40_is_idempotent(tmp_path):
    """Running the migration twice in a row is a no-op the second time."""
    db_path = tmp_path / "twice.duckdb"
    conn = duckdb.connect(str(db_path))
    init_database(conn)
    conn.close()
    conn = duckdb.connect(str(db_path))
    init_database(conn)
    version = conn.execute("SELECT MAX(version) FROM schema_version").fetchone()[0]
    assert version == SCHEMA_VERSION
    conn.close()


def test_v30_db_ladders_all_the_way_up(tmp_path):
    """Representative evolved-DB test: an instance hand-rolled at v30 must
    ladder through to v40 without data loss, mirroring a customer who's
    been upgrading regularly since older releases."""
    db_path = tmp_path / "v30.duckdb"
    conn = duckdb.connect(str(db_path))
    conn.execute("""
        CREATE TABLE audit_log (
            id VARCHAR PRIMARY KEY,
            timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp,
            user_id VARCHAR,
            action VARCHAR NOT NULL,
            resource VARCHAR,
            params JSON,
            result VARCHAR,
            duration_ms INTEGER
        )
    """)
    conn.execute(
        "CREATE TABLE schema_version (version INTEGER, "
        "applied_at TIMESTAMP DEFAULT current_timestamp)"
    )
    conn.execute("INSERT INTO schema_version (version) VALUES (30)")
    conn.execute("INSERT INTO audit_log (id, action) VALUES ('vintage', 'test.x')")
    conn.close()

    conn = duckdb.connect(str(db_path))
    init_database(conn)
    version = conn.execute("SELECT MAX(version) FROM schema_version").fetchone()[0]
    assert version == SCHEMA_VERSION
    assert conn.execute("SELECT COUNT(*) FROM audit_log WHERE id='vintage'").fetchone()[0] == 1
    conn.close()


def test_v39_db_upgrades_cleanly(tmp_path):
    """A DB hand-rolled at v39 (audit_log without the four new columns)
    must upgrade to v40 without data loss."""
    db_path = tmp_path / "v39.duckdb"
    conn = duckdb.connect(str(db_path))
    conn.execute("""
        CREATE TABLE audit_log (
            id VARCHAR PRIMARY KEY,
            timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp,
            user_id VARCHAR,
            action VARCHAR NOT NULL,
            resource VARCHAR,
            params JSON,
            result VARCHAR,
            duration_ms INTEGER
        )
    """)
    conn.execute(
        "CREATE TABLE schema_version (version INTEGER, "
        "applied_at TIMESTAMP DEFAULT current_timestamp)"
    )
    conn.execute("INSERT INTO schema_version (version) VALUES (39)")
    conn.execute("INSERT INTO audit_log (id, action) VALUES ('row1', 'test.action')")
    conn.close()

    conn = duckdb.connect(str(db_path))
    init_database(conn)
    version = conn.execute("SELECT MAX(version) FROM schema_version").fetchone()[0]
    assert version == SCHEMA_VERSION
    cnt = conn.execute("SELECT COUNT(*) FROM audit_log WHERE id='row1'").fetchone()[0]
    assert cnt == 1
    row = conn.execute(
        "SELECT params_before, client_ip, client_kind, correlation_id FROM audit_log WHERE id='row1'"
    ).fetchone()
    assert row == (None, None, None, None)
    conn.close()
