"""PAPER-152's resolution half — the gate resolves members at origin/<default>.

THE INCIDENT THESE PIN (2026-08-06). 0.25.0 shipped the `registry-consistency`
audit check to the fleet. That check consumes `run_registry(check=True)`, which
shelled the mgf-standard generator against the BENCH's working trees — PAPER-152's
defect, on a surface the paper had not seen. mgf-standard's pipelines
(515/517) went red with 9 findings, 8 of which were the founder's parked
checkouts being reported as fleet defects. Their auditor pip-installs mgf-fed
unpinned, so it picked up 0.25.0 mid-queue, and their repo had deliberately
removed pre-check waivers (f892393) — so there was nothing to absorb it.

TWO defects, and the second one was mine:

  A. The 8 bench findings were the DIVERGENCE BANNER, verbatim. 0.25.0 printed it
     to stdout; `check_registry_consistency` captures `run_registry`'s stdout and
     parses every `- <text>` line into a Finding — which is exactly the banner's
     member-list shape, capped at 8, hence exactly 8. A diagnostic shared a
     channel AND a shape with the data it annotated. Fixed by moving the banner to
     stderr (pinned in test_roster.py).
  B. The underlying working-tree read — this file. Bench divergence is CONTEXT
     (a banner), never a finding; the check's findings are only true
     registry↔origin-default disagreements.

The generator is mgf-standard's file and this repo is read-only on it (FB-05), so
what mgf-fed fixed is what it owns: the ROOT it points the generator at. These
fixtures therefore drive a STUB generator — the seam under test is which tree is
handed over, not the generator's own logic, which is tested where it lives.
"""

from __future__ import annotations

import shutil
import subprocess
from pathlib import Path

import pytest

from mgf.fed import _origin_view
from mgf.fed._registry import run_registry

requires_git = pytest.mark.skipif(
    shutil.which("git") is None, reason="git not on PATH (e.g. the slim CI image)"
)


def _git(cwd: Path, *args: str) -> None:
    subprocess.run(  # noqa: S603 — fixed git argv over a tmp_path fixture
        ["git", "-C", str(cwd), *args],  # noqa: S607
        check=True,
        capture_output=True,
    )


def _init(d: Path) -> None:
    d.mkdir(parents=True, exist_ok=True)
    _git(d, "init", "--quiet", "--initial-branch=main")
    _git(d, "config", "user.email", "fixture@example.invalid")
    _git(d, "config", "user.name", "fixture")
    _git(d, "config", "commit.gpgsign", "false")


def _commit(d: Path, msg: str) -> str:
    _git(d, "add", "-A")
    _git(d, "commit", "--quiet", "-m", msg)
    return subprocess.run(  # noqa: S603
        ["git", "-C", str(d), "rev-parse", "HEAD"],  # noqa: S607
        check=True,
        capture_output=True,
        text=True,
    ).stdout.strip()


def _publish(d: Path, sha: str) -> None:
    """Synthesise what a clone leaves behind: origin/main + origin/HEAD."""
    _git(d, "update-ref", "refs/remotes/origin/main", sha)
    _git(d, "symbolic-ref", "refs/remotes/origin/HEAD", "refs/remotes/origin/main")


#: A stand-in for mgf-standard's generator. It answers the one question the real one
#: answers — "does each member's committed pin agree with the registry?" — in the
#: real one's output format (`  - <detail>` to stderr, exit 1), which is the format
#: `check_registry_consistency` parses. It reports the ROOT it walked, so a test can
#: prove WHICH tree was handed to it.
_STUB_GENERATOR = """\
import sys
from pathlib import Path

repo_root = Path(__file__).resolve().parent.parent
federation_root = repo_root.parent
registry = (repo_root / "REGISTRY.txt").read_text().strip()

problems = []
for d in sorted(p for p in federation_root.iterdir() if p.is_dir()):
    pin = d / "pin.txt"
    if not pin.is_file():
        continue
    got = pin.read_text().strip()
    if got != registry:
        problems.append(f"{d.name} pins `{got}` but the registry says `{registry}`")

print(f"WALKED: {federation_root}")
if problems:
    print("FEDERATION CONSISTENCY GATE: RED", file=sys.stderr)
    for p in problems:
        print(f"  - {p}", file=sys.stderr)
    sys.exit(1)
print("FEDERATION CONSISTENCY GATE: GREEN")
"""


def _federation(tmp_path: Path, *, origin_pin: str, worktree_pin: str, registry: str) -> Path:
    """A two-repo federation whose member's ORIGIN pin and WORKING-TREE pin differ.

    That gap is the whole point: it is the bench state PAPER-152 is about, made
    small enough to assert on. `mgf-standard` carries the stub generator and the
    registry the member is graded against.
    """
    root = tmp_path / "fed"
    root.mkdir()

    std = root / "mgf-standard"
    _init(std)
    (std / "scripts").mkdir()
    (std / "scripts" / "gen_mgf_libraries.py").write_text(_STUB_GENERATOR, encoding="utf-8")
    (std / "REGISTRY.txt").write_text(registry + "\n", encoding="utf-8")
    _publish(std, _commit(std, "registry"))

    member = root / "mgf-member"
    _init(member)
    (member / "pin.txt").write_text(origin_pin + "\n", encoding="utf-8")
    _publish(member, _commit(member, "the pin as SHIPPED"))
    if worktree_pin != origin_pin:
        # Park the member on an unmerged branch — the bench state that must be
        # context, not a finding.
        _git(member, "checkout", "--quiet", "-b", "feat/parked")
        (member / "pin.txt").write_text(worktree_pin + "\n", encoding="utf-8")
        _commit(member, "unshipped work")
    return root


@requires_git
class TestTheGateResolvesAtOriginDefault:
    def test_a_parked_member_produces_NO_finding_and_IS_named_in_the_banner(
        self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """The incident, in miniature. The member's SHIPPED pin agrees with the
        registry; only its parked working tree disagrees. Before the fix that was a
        RED naming the member; now it is a banner line and the gate is green."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="9.9-unshipped", registry="1.0")
        rc = run_registry(check=True, root=root)
        cap = capsys.readouterr()
        assert rc == 0, f"a parked checkout still reddened the gate:\n{cap.out}\n{cap.err}"
        assert "GATE: GREEN" in cap.out
        # ...and the bench state is not silently dropped: it is CONTEXT, on stderr.
        assert "DIVERGENT CHECKOUTS" in cap.err
        assert "mgf-member" in cap.err
        assert "feat/parked" in cap.err
        # The banner must never reach the stream the audit parses into findings.
        assert "DIVERGENT CHECKOUTS" not in cap.out
        assert "mgf-member — on feat/parked" not in cap.out

    def test_a_real_origin_default_disagreement_IS_still_found(
        self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """The check keeps its teeth. Same shape, but the SHIPPED pin is the wrong
        one — a true registry↔origin-default disagreement, which must red."""
        root = _federation(tmp_path, origin_pin="0.1-stale", worktree_pin="1.0", registry="1.0")
        rc = run_registry(check=True, root=root)
        cap = capsys.readouterr()
        assert rc == 1
        assert "mgf-member pins `0.1-stale`" in cap.out
        # and NOT the working tree's (correct) pin — the verdict is about the remote
        assert "`1.0` but the registry" not in cap.out

    def test_the_generator_is_pointed_at_the_MIRROR_not_at_the_bench(
        self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """The seam itself, asserted directly: the root the generator walks is not
        the federation root. This is the one-line difference the incident turned on."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        run_registry(check=True, root=root)
        walked = [ln for ln in capsys.readouterr().out.splitlines() if ln.startswith("WALKED: ")]
        assert walked, "the stub generator did not report its root"
        assert walked[0] != f"WALKED: {root}"

    def test_source_worktree_is_the_deliberate_local_preview(
        self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """PAPER-152's third offer. The escape hatch still grades the bench — and
        says so, so a red from it is never mistaken for a fleet red."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="9.9-unshipped", registry="1.0")
        rc = run_registry(check=True, root=root, source="worktree")
        cap = capsys.readouterr()
        assert rc == 1  # the bench really does disagree
        assert "mgf-member pins `9.9-unshipped`" in cap.out
        assert "does not describe any remote" in cap.err
        assert f"WALKED: {root}" in cap.out  # the bench itself, not a mirror

    def test_an_unknown_source_is_refused_rather_than_guessed(self, tmp_path: Path) -> None:
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        assert run_registry(check=True, root=root, source="bench") == 2


@requires_git
class TestDegradationIsLoud:
    def test_a_member_with_no_origin_falls_back_and_is_NAMED(self, tmp_path: Path) -> None:
        """The honesty rule. A member that cannot be resolved at origin is graded
        from its working tree — which is the only thing left — but it is NEVER
        silent, because a verdict part-assembled from unshipped state while
        claiming to describe the remote is the failure this paper is about."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        orphan = root / "mgf-orphan"
        _init(orphan)  # a real repo, but no `origin` remote at all
        (orphan / "pin.txt").write_text("1.0\n", encoding="utf-8")
        _commit(orphan, "local only")

        view = _origin_view.materialize(root, tmp_path / "mirror")
        assert dict(view.degraded).keys() == {"mgf-orphan"}
        assert not view.fully_truthful
        banner = view.degradation_banner()
        assert "ORIGIN-DEFAULT VIEW INCOMPLETE" in banner
        assert "mgf-orphan" in banner
        assert "no origin default branch" in banner
        # the fallback really happened — its file is in the mirror
        assert (view.root / "mgf-orphan" / "pin.txt").read_text().strip() == "1.0"

    def test_a_fully_resolvable_federation_degrades_NOTHING(self, tmp_path: Path) -> None:
        """The control: the banner must stay silent when there is nothing to say,
        or it becomes noise operators learn to skip."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        view = _origin_view.materialize(root, tmp_path / "mirror")
        assert view.degraded == ()
        assert view.fully_truthful
        assert view.degradation_banner() == ""
        assert set(view.resolved) == {"mgf-standard", "mgf-member"}

    def test_no_git_binary_degrades_EVERY_member_loudly(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """The offline/toolless bench. Every member falls back, every one is named,
        and nothing raises — the shape `python:*-slim` actually produces."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        monkeypatch.setattr(_origin_view.shutil, "which", lambda _n: None)
        view = _origin_view.materialize(root, tmp_path / "mirror")
        assert view.resolved == ()
        assert {r for r, _ in view.degraded} == {"mgf-standard", "mgf-member"}
        assert all("git is not on PATH" in why for _r, why in view.degraded)
        assert "ORIGIN-DEFAULT VIEW INCOMPLETE" in view.degradation_banner()

    def test_the_mirror_is_BYTE_exact(self, tmp_path: Path) -> None:
        """`check_currency` compares the committed registry byte-for-byte against a
        fresh render, so a mirror that normalised whitespace would manufacture a
        false STALE — the fix inventing the very false verdict it exists to remove."""
        root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
        member = root / "mgf-member"
        awkward = "trailing-blank-lines\n\n\n"
        (member / "odd.txt").write_text(awkward, encoding="utf-8")
        _publish(member, _commit(member, "awkward bytes"))
        view = _origin_view.materialize(root, tmp_path / "mirror")
        assert (view.root / "mgf-member" / "odd.txt").read_bytes() == awkward.encode()


@requires_git
def test_the_mirror_needs_no_knowledge_of_what_the_generator_reads(tmp_path: Path) -> None:
    """Why every top-level blob, not a known file list.

    Mirroring "the files the generator needs" would be a second two-map lockstep
    across two independently-released repos — the defect 0.25.0 had just fixed in
    `_catch_up._scaffold_dest` (mgf-standard PAPER-148). A file the generator
    starts reading must already be present, with no mgf-fed release required.
    """
    root = _federation(tmp_path, origin_pin="1.0", worktree_pin="1.0", registry="1.0")
    member = root / "mgf-member"
    (member / "A_FILE_NO_ONE_HAS_HEARD_OF.toml").write_text("x = 1\n", encoding="utf-8")
    _publish(member, _commit(member, "a manifest from the future"))
    view = _origin_view.materialize(root, tmp_path / "mirror")
    assert (view.root / "mgf-member" / "A_FILE_NO_ONE_HAS_HEARD_OF.toml").is_file()
    # ...and directories are not blobs: only top-level FILES are mirrored.
    assert not (view.root / "mgf-member" / ".git" / "config").exists()


@requires_git
def test_the_INCIDENT_itself_a_parked_bench_produces_no_audit_findings(tmp_path: Path) -> None:
    """End-to-end at the layer that went red: `check_registry_consistency`.

    This is mgf-standard pipelines 515/517 reproduced small. The check captures
    `run_registry`'s stdout and turns each `- <text>` line into a Finding. On
    2026-08-06 that yielded 9 findings, 8 of which were the divergence banner's
    member list — the founder's parked checkouts, reported as defects of the fleet.

    Both halves of the fix are asserted here together, because either alone still
    fails: the banner must not be on the parsed stream (defect A), and the graded
    tree must be origin/<default> (defect B).
    """
    from mgf.fed._audit import check_registry_consistency

    root = _federation(tmp_path, origin_pin="1.0", worktree_pin="9.9-unshipped", registry="1.0")
    # More parked members than the banner's 8-name cap, so a leak could not be missed.
    for i in range(9):
        extra = root / f"mgf-parked-{i:02d}"
        _init(extra)
        (extra / "pin.txt").write_text("1.0\n", encoding="utf-8")
        _publish(extra, _commit(extra, "shipped"))
        _git(extra, "checkout", "--quiet", "-b", "feat/parked")
        (extra / "unshipped.txt").write_text("x\n", encoding="utf-8")
        _commit(extra, "unshipped work")

    res = check_registry_consistency(root)
    assert res.skipped == ""
    assert res.findings == [], f"bench state was reported as fleet defects: {res.findings}"
    assert res.ok
