"""Tests for the scaffold seam: ``list_scaffold`` / ``read_scaffold``.

The canonical standardized git/CI scaffold artifacts (the AG-03
``prepare-commit-msg`` hook, the ``check_commit_trailers.py`` CI checker, and
that checker's unit test) are shipped as wheel data so ``mgf-common catch-up``
resolves the canonical text rather than carrying a drift-prone copy. These pin
the resolver behaviour AND the single-source-of-truth invariant: the
cookiecutter copies MUST match the canonical (so a fleet scaffold can't silently
diverge).

The third artifact is the gate's own proof (FEEDBACK **PAPER-148**): the
checker's docstring asserts the pure predicate is unit-tested, and that sentence
is read in every repo the scaffold reaches — so the assertions have to reach
them too, rather than each consumer forking a fixture for a file the federation
requires to stay byte-identical.
"""

from __future__ import annotations

from pathlib import Path

import pytest

import mgf.standard as ds

_REPO_ROOT = Path(__file__).resolve().parents[2]
_COOKIECUTTER = (
    _REPO_ROOT / "templates" / "cookiecutter-mgf-project" / "{{cookiecutter.project_slug}}"
)


class TestScaffoldSeam:
    def test_list_scaffold_is_the_three_artifacts(self) -> None:
        assert ds.list_scaffold() == [
            "check_commit_trailers.py",
            "prepare-commit-msg",
            "test_check_commit_trailers.py",
        ]

    def test_read_hook_returns_the_canonical_text(self) -> None:
        text = ds.read_scaffold("prepare-commit-msg")
        assert "interpret-trailers" in text  # the load-bearing line
        assert text == (_REPO_ROOT / ".githooks" / "prepare-commit-msg").read_text(encoding="utf-8")

    def test_read_checker_returns_the_canonical_text(self) -> None:
        text = ds.read_scaffold("check_commit_trailers.py")
        assert "def missing_trailers" in text
        assert text == (_REPO_ROOT / "scripts" / "check_commit_trailers.py").read_text(
            encoding="utf-8"
        )

    def test_read_checker_test_returns_the_canonical_text(self) -> None:
        text = ds.read_scaffold("test_check_commit_trailers.py")
        # The load-bearing line: the test resolves the script from the REPO ROOT,
        # two levels up from tests/unit/ — which is what lets the same bytes work
        # unchanged in any consumer that receives it (PAPER-148).
        assert 'parents[2] / "scripts" / "check_commit_trailers.py"' in text
        assert text == (_REPO_ROOT / "tests" / "unit" / "test_check_commit_trailers.py").read_text(
            encoding="utf-8"
        )

    def test_unknown_name_raises_with_available(self) -> None:
        with pytest.raises(FileNotFoundError) as exc:
            ds.read_scaffold("no-such-artifact")
        assert "prepare-commit-msg" in str(exc.value)


class TestCookiecutterCopiesArePinned:
    """DOC-18 — the cookiecutter ships physical copies; they MUST equal the
    canonical scaffold text so new repos never diverge from the source of truth."""

    def test_hook_copy_matches_canonical(self) -> None:
        copy = (_COOKIECUTTER / ".githooks" / "prepare-commit-msg").read_text(encoding="utf-8")
        assert copy == ds.read_scaffold("prepare-commit-msg")

    def test_checker_copy_matches_canonical(self) -> None:
        copy = (_COOKIECUTTER / "scripts" / "check_commit_trailers.py").read_text(encoding="utf-8")
        assert copy == ds.read_scaffold("check_commit_trailers.py")

    def test_checker_test_copy_matches_canonical(self) -> None:
        copy = (_COOKIECUTTER / "tests" / "unit" / "test_check_commit_trailers.py").read_text(
            encoding="utf-8"
        )
        assert copy == ds.read_scaffold("test_check_commit_trailers.py")

    def test_checker_test_copy_sits_two_levels_under_the_project_root(self) -> None:
        """The mirror's *location* is load-bearing, not just its bytes.

        The test resolves the script it exercises as ``parents[2]/scripts/...``.
        Placed anywhere but ``<project>/tests/unit/`` — e.g. flat in ``tests/``
        beside ``test_smoke.py`` — that walk lands OUTSIDE the generated project
        and the file breaks on import. A generated project must therefore carry
        it at exactly this depth.
        """
        mirror = _COOKIECUTTER / "tests" / "unit" / "test_check_commit_trailers.py"
        assert mirror.is_file()
        assert mirror.resolve().parents[2] == _COOKIECUTTER.resolve()
        assert (_COOKIECUTTER / "scripts" / "check_commit_trailers.py").is_file()


class TestTemplatesCopyIsPinned:
    """``templates/check_commit_trailers.py`` is the third byte-identical copy.

    ``templates/policy.toml`` ``[exact]`` maps a member's
    ``scripts/check_commit_trailers.py`` to it, so ``mgf-fed drift-check`` grades
    every repo in the fleet against these bytes — but that comparator lives in
    another repo and cannot run in this repo's gates (see ``CONTRIBUTING.md``
    ``## CI delta``). Nothing here noticed if the template copy drifted from the
    source of truth. This is that pin, on the near side of the seam.
    """

    def test_templates_copy_matches_canonical(self) -> None:
        copy = (_REPO_ROOT / "templates" / "check_commit_trailers.py").read_text(encoding="utf-8")
        assert copy == ds.read_scaffold("check_commit_trailers.py")

    def test_policy_exact_map_points_at_that_copy(self) -> None:
        # The pin is only meaningful while policy.toml still routes drift-check
        # at the file this test compares.
        policy = (_REPO_ROOT / "templates" / "policy.toml").read_text(encoding="utf-8")
        assert '"scripts/check_commit_trailers.py" = "check_commit_trailers.py"' in policy
