from __future__ import annotations

import os
import shutil
import sqlite3
import subprocess
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[1]
SCRIPT = REPO_ROOT / "scripts" / "backup-db.sh"


def _run(args: list[str], env_overrides: dict[str, str], cwd: Path):
    env = os.environ.copy()
    env.update(env_overrides)
    return subprocess.run(
        [str(SCRIPT), *args],
        check=False,
        capture_output=True,
        text=True,
        cwd=str(cwd),
        env=env,
    )


def test_backup_exit_zero_when_db_missing(tmp_path):
    fake_db = tmp_path / "ghost.db"
    result = _run(
        [],
        {"QUARTERMASTER_DB_URL": f"sqlite:///{fake_db}"},
        tmp_path,
    )
    assert result.returncode == 0, result.stderr
    assert "nothing to back up" in result.stdout


def test_backup_creates_file(tmp_path):
    # seed a real sqlite DB
    db_path = tmp_path / "qm.db"
    conn = sqlite3.connect(str(db_path))
    conn.execute("CREATE TABLE t (x INTEGER)")
    conn.execute("INSERT INTO t VALUES (1), (2), (3)")
    conn.commit()
    conn.close()

    result = _run(
        ["unit-test"],
        {"QUARTERMASTER_DB_URL": f"sqlite:///{db_path}"},
        tmp_path,
    )
    assert result.returncode == 0, result.stderr
    backup_dir = tmp_path / "backups"
    assert backup_dir.is_dir()
    backups = list(backup_dir.glob("quartermaster-*-unit-test.db"))
    assert len(backups) == 1
    # restored backup reads the same rows
    restored = sqlite3.connect(str(backups[0]))
    rows = list(restored.execute("SELECT x FROM t ORDER BY x"))
    restored.close()
    assert rows == [(1,), (2,), (3,)]


def test_backup_rejects_non_sqlite_url(tmp_path):
    result = _run(
        [],
        {"QUARTERMASTER_DB_URL": "postgres://example"},
        tmp_path,
    )
    assert result.returncode == 1
    assert "not a sqlite URL" in result.stderr


def test_backup_slug_defaults_to_manual(tmp_path):
    db_path = tmp_path / "qm.db"
    sqlite3.connect(str(db_path)).close()
    result = _run(
        [],
        {"QUARTERMASTER_DB_URL": f"sqlite:///{db_path}"},
        tmp_path,
    )
    assert result.returncode == 0, result.stderr
    backups = list((tmp_path / "backups").glob("*manual*.db"))
    assert len(backups) == 1


def test_backup_slug_sanitizes_reason(tmp_path):
    db_path = tmp_path / "qm.db"
    sqlite3.connect(str(db_path)).close()
    result = _run(
        ["alembic upgrade!! head"],
        {"QUARTERMASTER_DB_URL": f"sqlite:///{db_path}"},
        tmp_path,
    )
    assert result.returncode == 0, result.stderr
    backups = list((tmp_path / "backups").glob("*.db"))
    assert len(backups) == 1
    assert "alembic-upgrade-head" in backups[0].name
