"""Single registry of input commands (slash and bang)."""

from typing import NamedTuple


class CommandInfo(NamedTuple):
    """Metadata for an input command."""

    desc: str
    arg: str | None = None
    arg_type: str | None = None
    kind: str = "state_change"
    modes: tuple[str, ...] = ("repl", "oneshot")
    options: tuple[tuple[str, str], ...] | None = None
    acp: bool = True


INPUT_COMMANDS: dict[str, CommandInfo] = {
    "!!": CommandInfo(
        desc="Run a shell command and print output (no LLM)",
        arg="<command>",
        kind="state_change",
        modes=("repl",),
        acp=False,
    ),
    "/audit": CommandInfo(
        desc="Run a staged security audit over tracked committed code",
        arg="[path|glob ...]",
        kind="agent_turn",
        modes=("repl", "oneshot"),
        options=(
            ("--resume", "Resume a previous audit run from its last checkpoint"),
            ("--regen", "Regenerate reports and patches for a completed audit run"),
            (
                "--finding N[,M-R]",
                "With --regen, regenerate only the selected 1-based Phase-5 "
                "findings (comma-separated values and ranges allowed)",
            ),
            (
                "--all",
                "Deep-review every file in scope; skip the triage selection",
            ),
            (
                "--measure-triage",
                "Calibration mode: run triage normally, then deep-review every "
                "file. Tags findings to expose Phase-2 false negatives.",
            ),
            ("--workers N", "Number of parallel verification workers (default: 4)"),
            (
                "--patch-max-turns N",
                "Phase-5 patch-generation turn budget (default: 50)",
            ),
            (
                "--debug",
                "Write a real-time JSONL debug log to .swival/audit/debug.jsonl",
            ),
        ),
    ),
    "/add-dir": CommandInfo(
        desc="Grant read+write access to a directory",
        arg="<path>",
        arg_type="dir_path",
        kind="state_change",
    ),
    "/add-dir-ro": CommandInfo(
        desc="Grant read-only access to a directory",
        arg="<path>",
        arg_type="dir_path",
        kind="state_change",
    ),
    "/clear": CommandInfo(
        desc="Reset conversation to initial state",
        kind="state_change",
    ),
    "/compact": CommandInfo(
        desc="Compress conversation context",
        kind="state_change",
        options=(("--drop", "Also remove middle turns for more aggressive reduction"),),
    ),
    "/continue": CommandInfo(
        desc="Reset turn counter and continue the agent loop",
        kind="agent_turn",
        modes=("repl",),
    ),
    "/copy": CommandInfo(
        desc="Copy last output to clipboard",
        kind="flow_control",
        modes=("repl",),
        acp=False,
    ),
    "/exit": CommandInfo(
        desc="Exit the REPL",
        kind="flow_control",
        acp=False,
    ),
    "/extend": CommandInfo(
        desc="Double max turns, or set to N",
        arg="[N]",
        kind="state_change",
    ),
    "/goal": CommandInfo(
        desc="Set, replace, pause, resume, or clear the persisted thread goal",
        arg="[<objective>|replace <objective>|pause|resume|clear]",
        kind="state_change",
        modes=("repl", "oneshot"),
    ),
    "/help": CommandInfo(
        desc="Show this help message",
        kind="info",
    ),
    "/init": CommandInfo(
        desc="Scan project for build/test/lint workflow and conventions, write AGENTS.md",
        kind="agent_turn",
    ),
    "/learn": CommandInfo(
        desc="Review session for mistakes and persist to memory",
        kind="agent_turn",
    ),
    "/loop": CommandInfo(
        desc="Run a plain prompt on a recurring interval (no slash bodies)",
        arg="[interval] <prompt>",
        kind="agent_turn",
        modes=("repl", "oneshot"),
        acp=False,
    ),
    "/loops": CommandInfo(
        desc="List active background loops (REPL only)",
        kind="info",
        modes=("repl",),
        acp=False,
    ),
    "/unloop": CommandInfo(
        desc="Cancel a background loop by id, or 'all'",
        arg="<id|all>",
        kind="state_change",
        modes=("repl",),
        acp=False,
    ),
    "/model": CommandInfo(
        desc="Switch model within the current provider (no arg = pick, - = revert)",
        arg="[name|-]",
        arg_type="model",
        kind="state_change",
        options=(("--fav [ID]", "Toggle favorite for the current or given model"),),
    ),
    "/new": CommandInfo(
        desc="Reset conversation to initial state",
        kind="state_change",
    ),
    "/profile": CommandInfo(
        desc="Switch LLM profile (no arg = list, - = revert)",
        arg="[name]",
        kind="state_change",
    ),
    "/quit": CommandInfo(
        desc="Exit the REPL",
        kind="flow_control",
        acp=False,
    ),
    "/remember": CommandInfo(
        desc="Add a durable project fact to AGENTS.md",
        arg="<text>",
        kind="state_change",
    ),
    "/restore": CommandInfo(
        desc="Summarize & collapse since checkpoint",
        kind="state_change",
    ),
    "/save": CommandInfo(
        desc="Set a context checkpoint",
        arg="[label]",
        kind="state_change",
    ),
    "/simplify": CommandInfo(
        desc="Simplify codebase (optionally scoped to focus area)",
        arg="[focus]",
        kind="agent_turn",
    ),
    "/status": CommandInfo(
        desc="Show session stats (model, context, turns, state)",
        kind="info",
    ),
    "/tools": CommandInfo(
        desc="List all available tools",
        kind="info",
    ),
    "/unsave": CommandInfo(
        desc="Cancel active checkpoint",
        kind="state_change",
    ),
}
