"""TS-01: ``tests/`` mirrors ``src/`` 1:1.

CI lint — every source module under ``src/mgf/common/`` MUST have a
corresponding ``tests/unit/.../test_<name>.py`` mirror, OR be listed in
``tests/MIRROR_ALLOWLIST.txt`` with a reason (the rule's documented
allow-list). A new source module added without either fails here, which is
exactly the drift TS-01 prevents.

Package ``__init__.py`` files are exempt (they are covered by the tests of
the package's members + the public-surface suite); the allow-list documents
the per-module exemptions (re-export shims, phase-test-covered CLI modules).
"""

from __future__ import annotations

from pathlib import Path

_TESTS = Path(__file__).resolve().parent
_ROOT = _TESTS.parent
_PKG = _ROOT / "src" / "mgf" / "common"
_ALLOWLIST = _TESTS / "MIRROR_ALLOWLIST.txt"


def _allowlist() -> set[str]:
    if not _ALLOWLIST.is_file():
        return set()
    return {
        ln.strip()
        for ln in _ALLOWLIST.read_text(encoding="utf-8").splitlines()
        if ln.strip() and not ln.lstrip().startswith("#")
    }


def _candidate_mirrors(rel: Path) -> list[Path]:
    """Test files that count as a mirror for a source module.

    Accepts mgf-common's real conventions: a leading underscore on the impl
    module is optional in the test name (``_lifecycle.py`` → ``test_lifecycle``),
    and the mirror may sit in the path-mirrored ``tests/unit/<dir>/`` OR at the
    ``tests/unit/`` root (where cross-cutting tests live).
    """
    stems = {rel.stem, rel.stem.lstrip("_")}
    dirs = {_TESTS / "unit" / rel.parent, _TESTS / "unit"}
    return [d / f"test_{s}.py" for d in dirs for s in sorted(stems)]


def _has_mirror(rel: Path) -> bool:
    return any(p.exists() for p in _candidate_mirrors(rel))


def _source_modules() -> list[Path]:
    out: list[Path] = []
    for p in _PKG.rglob("*.py"):
        if "__pycache__" in p.parts or p.name == "__init__.py":
            continue
        out.append(p)
    return out


def test_every_source_module_has_a_mirror_or_allowlist_entry() -> None:
    allow = _allowlist()
    missing: list[str] = []
    for src in _source_modules():
        rel = src.relative_to(_PKG)
        if rel.as_posix() in allow:
            continue
        if not _has_mirror(rel):
            missing.append(rel.as_posix())
    assert not missing, (
        "TS-01: source modules with no test mirror and no MIRROR_ALLOWLIST "
        "entry:\n  "
        + "\n  ".join(sorted(missing))
        + "\nAdd a `tests/unit/.../test_<name>.py` mirror, or list the module "
        "in tests/MIRROR_ALLOWLIST.txt with a one-line reason."
    )


def test_allowlist_has_no_stale_entries() -> None:
    """An allow-list entry that now HAS a mirror (or no longer exists) is
    stale — keep the list honest."""
    rels = {p.relative_to(_PKG).as_posix() for p in _source_modules()}
    stale: list[str] = []
    for entry in _allowlist():
        src = _PKG / entry
        if not src.exists():
            stale.append(f"{entry} (source gone)")
        elif entry not in rels:
            stale.append(f"{entry} (not a source module)")
        elif _has_mirror(Path(entry)):
            stale.append(f"{entry} (now has a mirror — remove from allow-list)")
    assert not stale, "TS-01: stale MIRROR_ALLOWLIST entries:\n  " + "\n  ".join(stale)
