"""PRAGMA user_version-based migration runner.

Each migration is a `.sql` file under `backend/src/cyclone/migrations/`
with a leading comment of the form `-- version: N`. The runner reads
the current `PRAGMA user_version`, sorts migrations by filename, and
applies any whose version is greater than the current value. Each
migration runs in its own transaction; a failure rolls back the
version bump so the next startup retries.

This is intentionally NOT Alembic. One operator, one machine, one
schema-version counter.

Convention: migrations are DDL-only. Do not use `--` comments except for the
required `-- version: N` header. Do not use string literals containing `;`.
This is enforced by the line-based comment stripper and naive `;` splitter.
"""

from __future__ import annotations

import re
from pathlib import Path

import sqlalchemy as sa

MIGRATIONS_DIR = Path(__file__).parent / "migrations"

_VERSION_RE = re.compile(r"^--\s*version:\s*(\d+)", re.MULTILINE)


def _migration_version(sql: str, filename: str) -> int:
    m = _VERSION_RE.search(sql)
    if not m:
        raise RuntimeError(
            f"{filename}: missing '-- version: N' header comment"
        )
    return int(m.group(1))


def _strip_comments(sql: str) -> str:
    """Remove `--` line comments; preserve everything else."""
    lines = []
    for line in sql.splitlines():
        stripped = line.strip()
        if stripped.startswith("--"):
            continue
        lines.append(line)
    return "\n".join(lines)


def run(engine: sa.Engine) -> None:
    """Apply any pending migrations. Idempotent."""
    migrations_dir = MIGRATIONS_DIR
    if not migrations_dir.exists():
        return  # no migrations directory yet — fresh checkout, no-op

    migration_files = sorted(migrations_dir.glob("*.sql"))
    if not migration_files:
        return

    with engine.begin() as conn:
        current = conn.exec_driver_sql("PRAGMA user_version").scalar() or 0

    for path in migration_files:
        sql = path.read_text()
        version = _migration_version(sql, path.name)
        if version <= current:
            continue

        statements_sql = _strip_comments(sql)
        statements = [s.strip() for s in statements_sql.split(";") if s.strip()]

        with engine.begin() as conn:
            for stmt in statements:
                conn.exec_driver_sql(stmt)
            conn.exec_driver_sql(f"PRAGMA user_version = {version}")

        current = version