"""Entry point for ``mgf-apiprobe`` and the ``apiprobe`` short alias.

Wires argparse to the per-subcommand handlers + routes through
:func:`mgf.common.cli.run_and_translate` for exit-code translation
of typed exceptions.
"""

from __future__ import annotations

import argparse
import importlib.metadata
import platform
import subprocess
import sys
from pathlib import Path
from typing import TYPE_CHECKING

from mgf.common.cli import run_and_translate

from mgf.apiprobe._version import __version__
from mgf.apiprobe.cli.bundle import handle_bundle
from mgf.apiprobe.cli.checks import handle_checks
from mgf.apiprobe.cli.doctor import handle_doctor
from mgf.apiprobe.cli.explain import handle_explain
from mgf.apiprobe.cli.run import handle_run

if TYPE_CHECKING:
    from collections.abc import Sequence


def _dep(pkg: str) -> str:
    try:
        return importlib.metadata.version(pkg)
    except importlib.metadata.PackageNotFoundError:  # pragma: no cover
        return "?"


def _rich_version() -> str:
    """OP-01 rich version: package + git SHA + Python + key deps."""
    sha = ""
    try:
        cmd = ["git", "-C", str(Path(__file__).resolve().parent), "rev-parse", "--short", "HEAD"]
        proc = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
        sha = proc.stdout.strip() if proc.returncode == 0 else ""
    except (OSError, subprocess.SubprocessError):  # pragma: no cover
        sha = ""
    head = f"apiprobe {__version__}" + (f" ({sha})" if sha else "")
    return (
        f"{head} | Python {platform.python_version()} "
        f"| mgf-common {_dep('mgf-common')} | httpx {_dep('httpx')}"
    )


def build_parser() -> argparse.ArgumentParser:
    """Build the top-level argparse parser."""
    parser = argparse.ArgumentParser(
        prog="apiprobe",
        description=(
            "REST API verification — typed probes, checks, findings. "
            "See https://codeberg.org/magogi-admin/mgf-apiprobe."
        ),
    )
    parser.add_argument(
        "--version",
        action="version",
        version=_rich_version(),
        help="Show version (package + git SHA + Python + key deps) and exit.",
    )
    sub = parser.add_subparsers(dest="subcommand", required=True)

    # apiprobe run
    p_run = sub.add_parser(
        "run",
        help="Execute a suite and print the report.",
    )
    p_run.add_argument(
        "--suite",
        metavar="MODULE[:ATTR]",
        default=None,
        help=(
            "Python module path to a suite (e.g., 'my.module:my_suite'). "
            "If omitted, runs the bundled httpbin self-test."
        ),
    )
    p_run.add_argument(
        "--format",
        choices=["human", "json"],
        default="human",
        help="Report format. Default: human.",
    )

    # apiprobe checks
    sub.add_parser(
        "checks",
        help="List the default check catalogue.",
    )

    # apiprobe doctor
    sub.add_parser(
        "doctor",
        help="Self-check — version, imports, default check count.",
    )

    # apiprobe explain
    sub.add_parser(
        "explain",
        help="Print the effective configuration with provenance (secrets redacted).",
    )

    # apiprobe bundle
    p_bundle = sub.add_parser(
        "bundle",
        help="Write a diagnostic tarball (system info + redacted config + doctor).",
    )
    p_bundle.add_argument(
        "--out",
        metavar="PATH",
        default=None,
        help="Output path. Default: ./apiprobe-diagnostic-bundle.tar.gz",
    )

    return parser


def _dispatch(argv: Sequence[str]) -> int:
    """Dispatch to the requested subcommand."""
    parser = build_parser()
    args = parser.parse_args(argv)
    if args.subcommand == "run":
        return handle_run(suite_path=args.suite, format=args.format)
    if args.subcommand == "checks":
        return handle_checks()
    if args.subcommand == "doctor":
        return handle_doctor()
    if args.subcommand == "explain":
        return handle_explain()
    if args.subcommand == "bundle":
        return handle_bundle(out=args.out)
    parser.error(f"unknown subcommand {args.subcommand!r}")  # pragma: no cover
    return 2  # pragma: no cover


def main(argv: Sequence[str] | None = None) -> int:
    """Translate typed exceptions to exit codes and dispatch.

    Does NOT configure logging — that is the console entry's job (:func:`_entry`),
    so importing or calling ``main`` from tests / library code never mutates global
    logging state.
    """
    if argv is None:
        argv = sys.argv[1:]
    return run_and_translate(_dispatch, list(argv))


def _entry() -> int:
    """Console-script entry — configure logging once (LG-02/06), then dispatch.

    The ``mgf-apiprobe`` / ``apiprobe`` console scripts point here. ``bootstrap``
    installs the federation JSON log formatter + sink (JSON to stderr when stdout is
    not a TTY) so suite logs, the operation span (LG-11), and events (LG-15) are captured.
    """
    from mgf.common import bootstrap

    bootstrap(app_name="apiprobe", app_version=__version__)
    return main()


if __name__ == "__main__":  # pragma: no cover
    sys.exit(_entry())
