"""Smoke tests for the dead_man.sh shell watchdog."""

from __future__ import annotations

import shutil
import sqlite3
import subprocess
from datetime import UTC, datetime, timedelta
from pathlib import Path

import pytest

REPO_ROOT = Path(__file__).resolve().parents[2]
SCRIPT = REPO_ROOT / "scripts" / "dead_man.sh"

_SQLITE3_BIN = shutil.which("sqlite3")

pytestmark = [
    pytest.mark.integration,
]


def _require_sqlite3() -> None:
    if _SQLITE3_BIN is None:
        pytest.skip("sqlite3 CLI not installed on this host")


def _setup_project(tmp_path: Path) -> Path:
    project = tmp_path / "project"
    (project / "data" / "log").mkdir(parents=True)
    (project / "scripts").mkdir(parents=True)
    shutil.copy(SCRIPT, project / "scripts" / "dead_man.sh")
    return project


def _write_health(project: Path, ts: datetime) -> None:
    log_file = project / "data" / "log" / f"cerbero-bite-{ts:%Y-%m-%d}.jsonl"
    log_file.write_text(
        f'{{"ts": "{ts.astimezone(UTC).isoformat()}", "event": "HEALTH_OK"}}\n',
        encoding="utf-8",
    )


def _run(project: Path, threshold: int = 900) -> subprocess.CompletedProcess[str]:
    return subprocess.run(
        ["bash", str(project / "scripts" / "dead_man.sh")],
        env={
            "PATH": "/usr/bin:/bin",
            "PROJECT_ROOT": str(project),
            "DEAD_MAN_THRESHOLD_SECONDS": str(threshold),
        },
        capture_output=True,
        text=True,
        check=False,
    )


def test_dead_man_exits_zero_when_recent_health_ok(tmp_path: Path) -> None:
    project = _setup_project(tmp_path)
    _write_health(project, datetime.now(UTC) - timedelta(seconds=60))
    result = _run(project, threshold=900)
    assert result.returncode == 0, result.stderr


def test_dead_man_arms_kill_switch_when_silent(tmp_path: Path) -> None:
    _require_sqlite3()
    project = _setup_project(tmp_path)
    _write_health(project, datetime.now(UTC) - timedelta(seconds=2000))

    # Pre-create the SQLite system_state singleton; otherwise the script
    # has nothing to update.
    db = project / "data" / "state.sqlite"
    conn = sqlite3.connect(str(db))
    conn.execute(
        "CREATE TABLE system_state (id INTEGER PRIMARY KEY CHECK(id=1), "
        "kill_switch INTEGER NOT NULL DEFAULT 0, kill_reason TEXT, "
        "kill_at TEXT, last_health_check TEXT NOT NULL, "
        "last_kelly_calib TEXT, config_version TEXT NOT NULL, "
        "started_at TEXT NOT NULL)"
    )
    conn.execute(
        "INSERT INTO system_state(id, last_health_check, config_version, started_at) "
        "VALUES (1, '2026-04-27', '1.0.0', '2026-04-27')"
    )
    conn.commit()
    conn.close()

    result = _run(project, threshold=900)
    assert result.returncode == 1

    # Kill switch armed.
    conn = sqlite3.connect(str(db))
    try:
        kill = conn.execute("SELECT kill_switch FROM system_state").fetchone()[0]
    finally:
        conn.close()
    assert kill == 1

    # Alert file exists.
    alert = project / "data" / "log" / "dead-man-alert.txt"
    assert alert.exists()
    assert "dead_man" in alert.read_text(encoding="utf-8")


def test_dead_man_handles_missing_log_file(tmp_path: Path) -> None:
    project = _setup_project(tmp_path)
    # No log file at all.
    result = _run(project, threshold=900)
    assert result.returncode == 1
    alert = project / "data" / "log" / "dead-man-alert.txt"
    assert alert.exists()
