"""Tests for clean-machine validation automation script."""

from __future__ import annotations

import json
import types
from pathlib import Path

import pytest

from scripts import validate_clean_machine as vcm


def _fake_completed(returncode=0, stdout="ok", stderr=""):
    return types.SimpleNamespace(returncode=returncode, stdout=stdout, stderr=stderr)


def test_run_checked_writes_log(monkeypatch, tmp_path):
    log_path = tmp_path / "cmd.log"

    def fake_run(*args, **kwargs):
        return _fake_completed(returncode=0, stdout="hello", stderr="world")

    monkeypatch.setattr(vcm.subprocess, "run", fake_run)
    elapsed = vcm.run_checked(
        ["python", "--version"],
        log_path=log_path,
        timeout_seconds=10,
        cwd=tmp_path,
    )

    assert elapsed >= 0
    assert log_path.exists()
    content = log_path.read_text(encoding="utf-8")
    assert "$ python --version" in content
    assert "hello" in content
    assert "world" in content


def test_run_validation_creates_artifacts(monkeypatch, tmp_path):
    artifact_dir = tmp_path / "artifacts"
    output_path = tmp_path / "models" / "demo.osmoimg"

    def fake_run(cmd, **kwargs):
        # Handle venv creation step
        if len(cmd) >= 4 and cmd[1:3] == ["-m", "venv"]:
            venv_dir = Path(cmd[3])
            py = vcm._venv_python(venv_dir)
            py.parent.mkdir(parents=True, exist_ok=True)
            py.write_text("", encoding="utf-8")
            return _fake_completed()
        return _fake_completed(returncode=0, stdout="ok", stderr="")

    monkeypatch.setattr(vcm.subprocess, "run", fake_run)
    monkeypatch.chdir(tmp_path)

    args = types.SimpleNamespace(
        install_spec=".[huggingface,compression]",
        model_id="HuggingFaceTB/SmolLM2-135M-Instruct",
        output=str(output_path.relative_to(tmp_path)),
        compression_profile="lossless-max",
        max_tokens=32,
        temperature=0.1,
        timeout_minutes=30.0,
        artifact_dir=str(artifact_dir.relative_to(tmp_path)),
    )

    summary = vcm.run_validation(args)

    assert summary["passed"] is True
    assert (artifact_dir / "01_pip_upgrade.log").exists()
    assert (artifact_dir / "02_pip_install.log").exists()
    assert (artifact_dir / "03_demo.log").exists()
    assert (artifact_dir / "04_inspect.log").exists()
    summary_file = artifact_dir / "summary.json"
    assert summary_file.exists()
    loaded = json.loads(summary_file.read_text(encoding="utf-8"))
    assert loaded["passed"] is True
    assert [s["name"] for s in loaded["steps"]] == [
        "create_venv",
        "pip_upgrade",
        "pip_install_spec",
        "run_demo",
        "inspect_output",
    ]


def test_run_validation_enforces_timeout(monkeypatch, tmp_path):
    artifact_dir = tmp_path / "artifacts"

    def fake_run(cmd, **kwargs):
        if len(cmd) >= 4 and cmd[1:3] == ["-m", "venv"]:
            venv_dir = Path(cmd[3])
            py = vcm._venv_python(venv_dir)
            py.parent.mkdir(parents=True, exist_ok=True)
            py.write_text("", encoding="utf-8")
        return _fake_completed()

    monkeypatch.setattr(vcm.subprocess, "run", fake_run)
    monkeypatch.chdir(tmp_path)
    monkeypatch.setattr(vcm, "run_checked", lambda *args, **kwargs: 0.01)

    # Force total elapsed to exceed timeout threshold.
    ticks = iter([0.0, 0.1, 0.2, 5000.0])
    monkeypatch.setattr(vcm.time, "perf_counter", lambda: next(ticks))

    args = types.SimpleNamespace(
        install_spec=".[huggingface,compression]",
        model_id="HuggingFaceTB/SmolLM2-135M-Instruct",
        output="models/demo.osmoimg",
        compression_profile="lossless-max",
        max_tokens=32,
        temperature=0.1,
        timeout_minutes=0.5,
        artifact_dir=str(artifact_dir.relative_to(tmp_path)),
    )

    with pytest.raises(RuntimeError, match="exceeded timeout"):
        vcm.run_validation(args)

    assert (artifact_dir / "summary.json").exists()
