"""Tests for the conformance-audit wrapper.

Mirrors ``tests/unit/test_registry.py`` because ``_conformance`` mirrors
``_registry``: both are thin, bounded wrappers over a script that lives in
mgf-standard. The behaviours worth pinning are the ones that make the wrapper
*honest* rather than merely functional — it must refuse clearly when the auditor
is absent, warn before writing a tracker nobody can date, and never translate a
timeout into a quiet success.
"""

from __future__ import annotations

import subprocess
from pathlib import Path

import pytest

from mgf.fed import _conformance
from mgf.fed._conformance import run_conformance


class _FakeProc:
    def __init__(self, returncode: int) -> None:
        self.returncode = returncode


def _with_auditor(tmp_path: Path) -> Path:
    """A root containing mgf-standard/scripts/fleet_conformance_audit.py."""
    audit = tmp_path / "mgf-standard" / "scripts" / "fleet_conformance_audit.py"
    audit.parent.mkdir(parents=True)
    audit.write_text("# auditor", encoding="utf-8")
    return tmp_path


def test_auditor_missing_is_a_clear_refusal(
    tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
    """Absent auditor -> 2 and a message naming the path, not a silent 0."""
    assert run_conformance(root=tmp_path) == 2
    out = capsys.readouterr().out
    assert "fleet_conformance_audit.py" in out
    assert "mgf-standard" in out


def test_returncode_propagates(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(_conformance.subprocess, "run", lambda *a, **k: _FakeProc(1))
    assert run_conformance(root=_with_auditor(tmp_path), generated="2026-07-29") == 1


def test_timeout_is_a_failure_not_a_pass(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    """A wrapper that can hang forever is its own outage — and one that swallows
    the timeout is worse, because the caller reads it as a completed audit."""

    def _boom(*a: object, **k: object) -> None:
        raise subprocess.TimeoutExpired(cmd="audit", timeout=1)

    monkeypatch.setattr(_conformance.subprocess, "run", _boom)
    assert run_conformance(root=_with_auditor(tmp_path), generated="2026-07-29") == 2
    assert "exceeded" in capsys.readouterr().out


def test_oserror_is_reported_not_raised(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    def _boom(*a: object, **k: object) -> None:
        raise OSError("no interpreter")

    monkeypatch.setattr(_conformance.subprocess, "run", _boom)
    assert run_conformance(root=_with_auditor(tmp_path), generated="2026-07-29") == 2
    assert "failed" in capsys.readouterr().out


def test_warns_when_the_tracker_would_be_unstamped(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    """No --generated and no AUDIT_TS means the script writes 'UNSTAMPED'.
    Say so BEFORE the run — an undated tracker can never be shown to be stale."""
    monkeypatch.delenv("AUDIT_TS", raising=False)
    monkeypatch.setattr(_conformance.subprocess, "run", lambda *a, **k: _FakeProc(0))
    assert run_conformance(root=_with_auditor(tmp_path)) == 0
    assert "UNSTAMPED" in capsys.readouterr().out


def test_no_warning_when_stamped(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    monkeypatch.setattr(_conformance.subprocess, "run", lambda *a, **k: _FakeProc(0))
    assert run_conformance(root=_with_auditor(tmp_path), generated="2026-07-29") == 0
    assert "UNSTAMPED" not in capsys.readouterr().out


def test_no_warning_when_audit_ts_is_set(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    monkeypatch.setenv("AUDIT_TS", "2026-07-29")
    monkeypatch.setattr(_conformance.subprocess, "run", lambda *a, **k: _FakeProc(0))
    assert run_conformance(root=_with_auditor(tmp_path)) == 0
    assert "UNSTAMPED" not in capsys.readouterr().out


def test_flags_reach_the_auditor(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    """--json-only, --generated and repeatable --extra-root must be forwarded.

    ``--extra-root`` exists because the auditor's own ``--root`` means *extra
    search root* while every mgf-fed verb's ``--root`` means *federation root*.
    Forwarding it under the wrong name would silently audit the wrong tree.
    """
    seen: dict[str, object] = {}

    def _capture(args: list[str], **kwargs: object) -> _FakeProc:
        seen["args"] = args
        seen["cwd"] = kwargs.get("cwd")
        return _FakeProc(0)

    monkeypatch.setattr(_conformance.subprocess, "run", _capture)
    root = _with_auditor(tmp_path)
    assert (
        run_conformance(
            json_only=True,
            generated="2026-07-29",
            extra_roots=("/srv/a", "/srv/b"),
            root=root,
        )
        == 0
    )
    args = seen["args"]
    assert isinstance(args, list)
    assert "--json-only" in args
    assert args[args.index("--generated") + 1] == "2026-07-29"
    assert args.count("--root") == 2
    assert "/srv/a" in args and "/srv/b" in args
    # runs INSIDE mgf-standard: the auditor resolves its output dir from its own repo
    assert str(seen["cwd"]) == str(root / "mgf-standard")


def test_streams_rather_than_capturing(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    """The audit drives catch-up across the fleet and runs for minutes. Capturing
    its output would make a working run indistinguishable from a hang."""
    seen: dict[str, object] = {}

    def _capture(args: list[str], **kwargs: object) -> _FakeProc:
        seen.update(kwargs)
        return _FakeProc(0)

    monkeypatch.setattr(_conformance.subprocess, "run", _capture)
    run_conformance(root=_with_auditor(tmp_path), generated="2026-07-29")
    assert not seen.get("capture_output")
    assert seen.get("timeout")  # bounded: a wrapper that can hang forever is an outage
