"""CLI dispatch tests — every subcommand routes to its handler."""

from __future__ import annotations

import argparse

import pytest

from mgf.fed import __main__ as _main
from mgf.fed.__main__ import main


def test_version_flag(capsys: pytest.CaptureFixture[str]) -> None:
    with pytest.raises(SystemExit) as exc:
        main(["--version"])
    assert exc.value.code == 0
    assert "mgf-fed" in capsys.readouterr().out


# Patch the SOURCE module of each handler (main() lazy-imports them after parse_args,
# so the dotted source path is what the `from ._x import run_x` binds — patching
# `__main__.run_x` would be shadowed by that re-import).
@pytest.mark.parametrize(
    ("argv", "target"),
    [
        (["status"], "mgf.fed._status.run_status"),
        (["drift-check"], "mgf.fed._drift.run_drift_check"),
        (["local-index"], "mgf.fed._index.run_local_index"),
        (["gates"], "mgf.fed._gates.run_gates"),
        (["local-ci", "mgf-http"], "mgf.fed._localci.run_local_ci"),
        (["release-local", "mgf-x"], "mgf.fed._release.release_local"),
        (["release-remote", "mgf-x"], "mgf.fed._release.release_remote"),
        (["scaffold", "mgf-x"], "mgf.fed._scaffold.run_scaffold"),
        (["registry"], "mgf.fed._registry.run_registry"),
    ],
)
def test_dispatch(monkeypatch: pytest.MonkeyPatch, argv: list[str], target: str) -> None:
    seen: dict[str, bool] = {}

    def _fake(*_a: object, **_k: object) -> int:
        seen["called"] = True
        return 0

    monkeypatch.setattr(target, _fake)
    assert main(argv) == 0
    assert seen.get("called") is True


def test_no_command_errors() -> None:
    with pytest.raises(SystemExit):
        main([])  # subparsers required=True → argparse exits non-zero


# ---------------------------------------------------------------------------
# PAPER-168 — a degraded install answered "invalid choice", not "I failed to load".
#
# `_add_registered_subcommands` guards the extended CLI behind `except
# ImportError: return`, deliberately, so the zero-dep orchestration core stays
# runnable. The guard is right; the SILENCE was not. Measured on this bench
# after a reinstall dropped `mgf-common`: `mgf-fed --help` listed 17 verbs
# instead of 43, and `mgf-fed app-doctor` said
#
#     invalid choice: 'app-doctor' (choose from status, drift-check, ...)
#
# which is indistinguishable from "that verb does not exist". The operator had
# no way to tell a missing feature from a broken environment — "I could not
# look" rendered as "there was nothing to see", the defect this repo exists to
# end, in its own front door.
# ---------------------------------------------------------------------------


def _parser_with_broken_extended_cli() -> argparse.ArgumentParser:
    """Build the parser with `mgf.common.cli` unimportable, as a bare install is."""
    import builtins

    real = builtins.__import__

    def fake(name: str, *a: object, **k: object) -> object:
        if name.startswith("mgf.common.cli"):
            raise ImportError("No module named 'mgf.common'")
        return real(name, *a, **k)  # type: ignore[arg-type]

    builtins.__import__ = fake  # type: ignore[assignment]
    try:
        return _main.build_parser()
    finally:
        builtins.__import__ = real  # type: ignore[assignment]


def test_degraded_install_announces_itself() -> None:
    """A half-loaded CLI must SAY so — in --help, where a confused user looks."""
    p = _parser_with_broken_extended_cli()
    assert p.epilog, "a degraded install produced no epilog — the silence is back"
    epilog = p.epilog
    assert "DEGRADED INSTALL" in epilog
    assert "invalid choice" in epilog, "must name the symptom the user actually sees"
    assert "mgf-common" in epilog, "must name the reason, not just the fact"
    assert "app-doctor" in epilog, "must name at least one verb that went missing"


def test_healthy_install_says_nothing() -> None:
    """The notice is a fault report, not decoration — a good install stays quiet."""
    p = _main.build_parser()
    assert not (p.epilog or ""), (
        f"healthy install emitted a degraded-install notice: {p.epilog!r}. "
        "If this fires, the extended CLI genuinely failed to import here."
    )
