"""mgf-fed CLI command registration (moved from mgf-common in the v0.47 reorg).

Importing this module registers every end-user / governance command
(``version`` / ``explain`` / ``validate`` / ``app-doctor`` / ``migrate`` /
``standards`` / ``agents`` / ``catch-up`` / …) into
:mod:`mgf.common.cli._subcommand_registry`. :mod:`mgf.fed.__main__` then
merges those registered subcommands into its native fleet-orchestration
parser, so they surface as ``mgf-fed <verb>``.

Two verbs were renamed here to avoid clashing with mgf-fed's native fleet
verbs of the same name (which mean something different): the consumer-app
health check ``doctor`` → ``app-doctor`` (mgf-fed ``doctor`` is the
*federation* self-check), and the FEEDBACK how-to ``feedback`` →
``feedback-howto`` (mgf-fed ``feedback`` relays outboxes, FB-05).

Argument parsing uses :mod:`argparse` from the stdlib — no dependency on
``click`` or ``typer``.

``main()`` is retained as a thin ``build_cli`` + ``dispatch`` entry used by a
handful of console-script-shaped pins (bare ``--version``, the
no-subcommand-help fallback); the live ``mgf-fed`` dispatch path is
:func:`mgf.fed.__main__.main`.
"""

from __future__ import annotations

import sys
from typing import TYPE_CHECKING

from mgf.common.cli import (
    build_cli,
    dispatch,
    register_cli_subcommand,
)

from mgf.fed.cli._agents import add_agents_args, run_agents
from mgf.fed.cli._bench import add_bench_args, run_bench
from mgf.fed.cli._bundle import add_bundle_args, run_bundle
from mgf.fed.cli._catch_up import add_catch_up_args, run_catch_up
from mgf.fed.cli._doctor import add_doctor_args, run_doctor
from mgf.fed.cli._explain import add_explain_args, run_explain
from mgf.fed.cli._federation import add_design_args, run_design, run_federation
from mgf.fed.cli._federation_sync import (
    add_federation_sync_args,
    run_federation_sync,
)
from mgf.fed.cli._feedback import add_feedback_args, run_feedback
from mgf.fed.cli._init_project import (
    add_init_project_args,
    run_init_project,
)
from mgf.fed.cli._logs import add_logs_args, run_logs
from mgf.fed.cli._migrate import add_migrate_args, run_migrate
from mgf.fed.cli._recipe_prompt import (
    add_adopt_prompt_args,
    add_new_project_prompt_args,
    add_onboard_prompt_args,
    run_adopt_prompt,
    run_new_project_prompt,
    run_onboard_prompt,
)
from mgf.fed.cli._standards import add_standards_args, run_standards
from mgf.fed.cli._start import add_start_args, run_start
from mgf.fed.cli._sync_prompt import add_sync_prompt_args, run_sync_prompt
from mgf.fed.cli._test import add_test_args, run_test
from mgf.fed.cli._validate import add_validate_args, run_validate
from mgf.fed.cli._version import add_version_args, render_version, run_version

if TYPE_CHECKING:
    from collections.abc import Sequence


# ---------------------------------------------------------------------------
# Built-in subcommand pre-registration
# ---------------------------------------------------------------------------
#
# Registered at module import time so any caller of ``build_cli`` /
# ``mgf.fed.cli._mgfcli.main`` finds the four built-ins available.
# Consumer-registered subcommands stack on top.

register_cli_subcommand(
    "version",
    handler=run_version,
    help="Print version + commit + Python/platform + key-dep versions (OP-01).",
    parser_setup=add_version_args,
)

register_cli_subcommand(
    "bundle",
    handler=run_bundle,
    help="Write a single redacted diagnostic tarball "
    "(version + explain + doctor + logs + crashes) (OP-07).",
    parser_setup=add_bundle_args,
)

register_cli_subcommand(
    "explain",
    handler=run_explain,
    help="Print the active MgfSettings with each field's source.",
    parser_setup=add_explain_args,
)

register_cli_subcommand(
    "validate",
    handler=run_validate,
    help="Validate a YAML config file against the MgfSettings schema.",
    parser_setup=add_validate_args,
)

register_cli_subcommand(
    # Renamed from "doctor" in the v0.47 reorg: mgf-fed already owns
    # `doctor` (the federation self-check). This is the consumer-app
    # install/wiring health check.
    "app-doctor",
    handler=run_doctor,
    help="Run a consumer app's install-state and wiring health checks.",
    parser_setup=add_doctor_args,
)

register_cli_subcommand(
    "migrate",
    handler=run_migrate,
    help=(
        "Apply mechanical renames to migrate consumer source from "
        "one mgf-common version to another."
    ),
    parser_setup=add_migrate_args,
)

register_cli_subcommand(
    "bench",
    handler=run_bench,
    help=(
        "Run microbench numbers for hot paths (current_context, bootstrap, log call, redaction)."
    ),
    parser_setup=add_bench_args,
)

register_cli_subcommand(
    "logs",
    handler=run_logs,
    help=(
        "Locate, read, and live-tail an app's logs: `logs info` (where + "
        "what components/levels), `logs tail` (last N), `logs follow` (live). "
        "Filters: --level / --component; --file / --app to target; --json."
    ),
    parser_setup=add_logs_args,
)

register_cli_subcommand(
    "standards",
    handler=run_standards,
    help=(
        "Print engineering-standards docs (DESIGN_PRINCIPLES, LOGGING, "
        "SECURITY, etc.) — single source of truth for cross-project rules."
    ),
    parser_setup=add_standards_args,
)

register_cli_subcommand(
    "federation",
    handler=run_federation,
    help=(
        "Print the federation contract (FEDERATION.md) — duties, layering, "
        "conformance levels — resolved from mgf-standard."
    ),
)

register_cli_subcommand(
    "design",
    handler=run_design,
    help=(
        "Print the foundation design papers (the WHY behind the rules); "
        "omit the name to list them. Resolved from mgf-standard."
    ),
    parser_setup=add_design_args,
)

register_cli_subcommand(
    "init-project",
    handler=run_init_project,
    help=(
        "Scaffold a new mgf-common-aligned project: docs/CLAUDE.md + "
        ".claude/settings.json + pyproject snippet for the four gates."
    ),
    parser_setup=add_init_project_args,
)

register_cli_subcommand(
    # Renamed from "feedback" in the v0.47 reorg: mgf-fed already owns
    # `feedback` (relay outboxes→inboxes, FB-05). This prints the
    # submission how-to + entry template.
    "feedback-howto",
    handler=run_feedback,
    help=(
        "Print the FEEDBACK.md submission flow + entry template — "
        "the canonical channel for sharp edges, roadmap requests, "
        "and design questions."
    ),
    parser_setup=add_feedback_args,
)

register_cli_subcommand(
    "catch-up",
    handler=run_catch_up,
    help=(
        "Audit an existing project against the current mgf-common "
        "engineering standards; --apply for mechanical fixes."
    ),
    parser_setup=add_catch_up_args,
)

register_cli_subcommand(
    "federation-sync",
    handler=run_federation_sync,
    help=(
        "Print the federation-sync message with the live pin window "
        "for the installed mgf-common (closes PAPER-57)."
    ),
    parser_setup=add_federation_sync_args,
)

register_cli_subcommand(
    "start",
    handler=run_start,
    help=(
        "THE federation front-door: one command for every onboarding case. "
        "Auto-detects a member (→ sync) or prints a scenario menu; "
        "--mode {new|onboard|sync|adopt} forces, --list shows the menu."
    ),
    parser_setup=add_start_args,
)

register_cli_subcommand(
    "sync-prompt",
    handler=run_sync_prompt,
    help=(
        "Print the federation sync/conformance prompt (the /sync recipe), "
        "resolved from mgf-standard — the single source of truth."
    ),
    parser_setup=add_sync_prompt_args,
)

register_cli_subcommand(
    "new-project-prompt",
    handler=run_new_project_prompt,
    help=(
        "Print the new-project bootstrap prompt (Case B — an empty repo becomes a "
        "federation member), resolved from mgf-standard."
    ),
    parser_setup=add_new_project_prompt_args,
)

register_cli_subcommand(
    "adopt-prompt",
    handler=run_adopt_prompt,
    help=(
        "Print the adopt prompt (Case C — a non-member understands/adopts the "
        "standards), resolved from mgf-standard."
    ),
    parser_setup=add_adopt_prompt_args,
)

register_cli_subcommand(
    "onboard-prompt",
    handler=run_onboard_prompt,
    help=(
        "Print the onboard prompt (Case — an existing external project becomes a "
        "federation member), resolved from mgf-standard."
    ),
    parser_setup=add_onboard_prompt_args,
)

register_cli_subcommand(
    "agents",
    handler=run_agents,
    help=(
        "Print the canonical Magogi agent briefing — the single, "
        "reliable message for any project's AI agent."
    ),
    parser_setup=add_agents_args,
)

register_cli_subcommand(
    "test",
    handler=run_test,
    help=(
        "Federation test supervisor (TS-22..TS-27 / TESTING.md "
        "§19) — run pytest with tiered selection (--tier N | N-M), "
        "time budgets (--budget T), auto-quarantine, structured "
        "JSONL outcomes, and per-failure detail bundles."
    ),
    parser_setup=add_test_args,
)


def main(argv: Sequence[str] | None = None) -> int:
    """Console-script entry point.

    Returns the exit code (NEVER raises). When called with no
    subcommand, prints the help text to stderr and returns
    :data:`mgf.common.cli.EXIT_UNKNOWN`. Dispatch flows through
    the v0.4 Phase E registry; consumer-registered subcommands
    are first-class.

    Sets identity to ``mgf-common-cli`` before dispatch (closes
    PAPER-19) so subcommands that read identity (``explain``,
    ``doctor``, future settings-aware surfaces) don't fire
    :class:`UnconfiguredWarning` on stderr and don't print
    ``vunknown`` placeholder banners. The CLI is a host process;
    setting identity is the honest fix.

    Why ``_set_identity`` instead of ``bootstrap_for_test``: a
    diagnostic CLI must not have side effects on the user's
    filesystem. ``bootstrap_for_test`` wires the rotating-file
    log handler, which writes to ``~/.local/state/mgf-common-cli/
    logs/...`` on every CLI invocation — wrong shape for ``mgf-
    common explain`` / ``doctor`` / ``standards``. The lighter
    ``_set_identity`` call sets the identity globals + flips
    ``_CONFIGURED=True`` (suppressing the warning chain in
    :func:`mgf.common._identity.app_name` /
    :func:`mgf.common.current_context`) without touching
    logging, OTel, excepthooks, or the filesystem.

    Note: this self-identity applies ONLY to the
    ``mgf-common`` console script. Consumers building their own
    top-level CLI via :func:`mgf.common.cli.build_cli` +
    :func:`mgf.common.cli.dispatch` are expected to bootstrap
    themselves (their consumer code IS the host); this function
    does not run for them.
    """
    if argv is None:
        argv = sys.argv[1:]

    # Rich `--version` / `-V` (OP-01): the console script answers the bare
    # flag, not just `mgf-fed version`. Intercepted before argparse so the
    # release-smoke `mgf-common --version` (WF-07) exits 0 instead of 2.
    if list(argv) and argv[0] in ("--version", "-V"):
        print(render_version())
        return 0

    # Set identity so subcommands can read app_name() / app_version()
    # without firing UnconfiguredWarning. No bootstrap, no logging
    # wiring, no filesystem side effects — diagnostic CLIs MUST stay
    # side-effect-free.
    from mgf.common import __version__, set_identity

    set_identity("mgf-common-cli", __version__)

    parser = build_cli()
    args = parser.parse_args(list(argv))
    return dispatch(args, parser=parser)


__all__ = [
    "main",
]
