"""``mgf-fed doctor`` — self-diagnostic (OP-02): probe mgf-fed's own operational prerequisites.

A pass/fail checklist of what mgf-fed needs to function — the federation root, the registry it
reads, the scaffolding policy, the local index — plus an informational note on which composed
external tools are on PATH (each command guards its own). Distinct from `drift-check`/`status`,
which probe the *federation*; this probes mgf-fed itself.
"""

from __future__ import annotations

import re
import shutil
import subprocess
from pathlib import Path

from mgf.fed import _index, _roster, _template

_COMPOSED_TOOLS = ("uv", "ruff", "git", "tea", "woodpecker-cli")


def _installed_is_current(root: Path) -> tuple[bool, str, str]:
    """Is the mgf-fed running this command the one on ``origin/main``?

    Board item 36. Sessions run `mgf-fed` from a uv-tool install that is a
    snapshot of whenever it was last installed. A gate can land on main, CI can
    start enforcing it, and the operator's own copy still lacks the check — so
    the bench and the pipeline disagree about what the rules are, silently. CI
    installs from the tree and is unaffected, which is precisely why this is easy
    to miss.

    Compares the running ``__version__`` to ``pyproject.toml`` on
    ``origin/main`` in the federation's own mgf-fed checkout. Unresolvable (no
    checkout, no git, no remote ref) reports as a pass with the reason stated —
    this is a convenience check, and failing a self-check because a clone is
    absent would be its own false alarm.
    """
    import mgf.fed as _self
    from mgf.fed import __version__

    repo = root / "mgf-fed"
    # The strongest answer is not a version comparison at all. If the running
    # module lives INSIDE the federation checkout, it is the checkout — an
    # editable install cannot drift. Only a snapshot copy can, and a snapshot
    # whose version happens to match still can, because code lands here without
    # a version bump all the time. So say which one is running.
    live = Path(_self.__file__ or "").resolve()
    if repo.resolve() in live.parents:
        return (
            True,
            f"mgf-fed runs from the checkout ({repo}) — cannot lag",
            "",
        )
    if not (repo / ".git").exists():
        return True, f"installed mgf-fed {__version__} (no mgf-fed checkout to compare against)", ""
    try:
        out = subprocess.run(  # noqa: S603
            ["git", "-C", str(repo), "show", "origin/main:pyproject.toml"],  # noqa: S607
            capture_output=True,
            text=True,
            timeout=30,
            check=False,
        )
    except (OSError, subprocess.SubprocessError) as exc:
        return True, f"installed mgf-fed {__version__} (cannot read origin/main: {exc})", ""
    if out.returncode != 0:
        return True, f"installed mgf-fed {__version__} (origin/main unavailable)", ""
    m = re.search(r'^version\s*=\s*"([^"]+)"', out.stdout, re.MULTILINE)
    if m is None:
        return True, f"installed mgf-fed {__version__} (no version on origin/main)", ""
    remote = m.group(1)
    head = subprocess.run(  # noqa: S603
        ["git", "-C", str(repo), "rev-parse", "--short", "origin/main"],  # noqa: S607
        capture_output=True,
        text=True,
        timeout=30,
        check=False,
    ).stdout.strip()
    return (
        __version__ == remote,
        f"installed mgf-fed {__version__} == origin/main {remote} — but this is a SNAPSHOT "
        f"install, and code lands without a version bump, so it may still lag "
        f"{head or 'origin/main'}. Prefer `uv tool install --force --editable {repo}`",
        f"installed {__version__}, origin/main is {remote} — "
        f"re-install: uv tool install --force --editable {repo}",
    )


def run_doctor(*, root: Path | None = None) -> int:
    root = root or _roster.federation_root()
    registry = root / "mgf-standard" / "MGF_LIBRARIES.json"
    # §3.3 precedence: [tool.mgf-fed.policy] in mgf-standard/pyproject.toml is
    # canonical; templates/policy.toml is the deprecated fallback.
    policy_src = _template.policy_source(root)

    checks: list[tuple[bool, str, str]] = [
        (
            root.is_dir(),
            f"federation root resolves ({root})",
            "set $MGF_ROOT or clone the fleet there",
        ),
        (
            registry.is_file(),
            "mgf-standard registry present (MGF_LIBRARIES.json)",
            "clone mgf-standard under the root",
        ),
        (
            policy_src is not None,
            f"scaffolding policy resolvable ({policy_src.name if policy_src else '—'})",
            "no [tool.mgf-fed.policy] in mgf-standard/pyproject.toml and no templates/policy.toml",
        ),
        (_index.local_index_dir().is_dir(), f"local index ready ({_index.local_index_dir()})", ""),
        _installed_is_current(root),
    ]

    print("mgf-fed doctor — self-check:")
    for ok, label, hint in checks:
        print(f"  {'✓' if ok else '✗'} {label}" + ("" if ok or not hint else f"  → {hint}"))
    for tool in _COMPOSED_TOOLS:
        present = shutil.which(tool) is not None
        print(
            f"  {'✓' if present else '·'} tool {tool}"
            + ("" if present else " (not on PATH — needed by some commands)")
        )

    core_ok = all(ok for ok, _, _ in checks)
    fails = sum(1 for ok, _, _ in checks if not ok)
    print(f"\n{'OK — prerequisites met' if core_ok else f'FAIL — {fails} prerequisite(s) missing'}")
    return 0 if core_ok else 1
