"""CLI entry point for Staso tooling.

Usage:
    staso setup      --target codex --api-key ak_... [options]
    staso uninstall  [--target codex]      # remove hooks and clean up
    staso sync       [--target codex]      # sync hooks for all or one agent
    staso update                           # upgrade SDK + sync hooks
    staso status     [--target codex]      # show current configuration
    staso version                          # version + latest available hint
    staso --version                        # same as above
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import tomllib
import warnings
from dataclasses import dataclass
from pathlib import Path


# -- agent registry ------------------------------------------------------------


@dataclass(frozen=True)
class AgentConfig:
    """Configuration for a CLI AI agent's hook integration."""

    name: str  # CLI flag value (e.g. "claude-code")
    module: str  # Python module under staso.* (e.g. "claude_code")
    display_name: str
    hook_events: tuple[str, ...]
    events_with_matcher: tuple[str, ...]
    global_settings: str  # path relative to $HOME
    project_settings: str  # path relative to cwd
    embed_env_in_command: bool = False  # prefix env vars in hook command


CLAUDE_CODE = AgentConfig(
    name="claude-code",
    module="claude_code",
    display_name="Claude Code",
    hook_events=(
        "SessionStart",
        "UserPromptSubmit",
        "PreToolUse",
        "PostToolUse",
        "PostToolUseFailure",
        "Stop",
        "StopFailure",
        "SubagentStart",
        "SubagentStop",
        "SessionEnd",
    ),
    events_with_matcher=("PreToolUse", "PostToolUse", "PostToolUseFailure"),
    global_settings=".claude/settings.json",
    project_settings=".claude/settings.local.json",
)

CODEX = AgentConfig(
    name="codex",
    module="codex",
    display_name="Codex",
    hook_events=(
        "SessionStart",
        "UserPromptSubmit",
        "PreToolUse",
        "PostToolUse",
        "Stop",
    ),
    events_with_matcher=("PreToolUse", "PostToolUse"),
    global_settings=".codex/hooks.json",
    project_settings=".codex/hooks.json",
    embed_env_in_command=True,
)

_AGENTS: dict[str, AgentConfig] = {
    "claude-code": CLAUDE_CODE,
    "codex": CODEX,
}


def get_agent(name: str) -> AgentConfig | None:
    return _AGENTS.get(name)


# -- kept for backward compat (imported by _common/repair.py) -----------------

_HOOK_EVENTS = CLAUDE_CODE.hook_events
_HOOK_EVENTS_WITH_MATCHER = CLAUDE_CODE.events_with_matcher


# -- hooks config builder -----------------------------------------------------


def _hook_entry(command: str, with_matcher: bool = False) -> dict:
    hook: dict = {"type": "command", "command": command}
    if with_matcher:
        return {"matcher": ".*", "hooks": [hook]}
    return {"hooks": [hook]}


def _build_hooks_config(command: str, agent: AgentConfig | None = None) -> dict:
    cfg = agent or CLAUDE_CODE
    hooks: dict = {}
    for event in cfg.hook_events:
        hooks[event] = [_hook_entry(command, with_matcher=event in cfg.events_with_matcher)]
    return hooks


def _merge_settings(existing: dict, new_hooks: dict, new_env: dict) -> dict:
    """Merge hook and env entries into existing settings, preserving unrelated keys."""
    result = dict(existing)

    existing_hooks = result.get("hooks", {})
    for event, entries in new_hooks.items():
        current = [
            e for e in existing_hooks.get(event, [])
            if not _is_staso_hook(e)
        ]
        current.extend(entries)
        existing_hooks[event] = current
    result["hooks"] = existing_hooks

    existing_env = result.get("env", {})
    existing_env.update(new_env)
    result["env"] = existing_env

    return result


def _is_staso_hook(entry: dict) -> bool:
    """Return True if this hook entry was written by Staso setup."""
    if "hooks" in entry:
        return any("staso." in h.get("command", "") for h in entry.get("hooks", []))
    return "staso." in entry.get("command", "")


# -- version with upgrade hint ------------------------------------------------


def _version_string() -> str:
    from staso._version import __version__

    line = f"staso {__version__}"
    latest = _check_latest_version()
    if latest and latest != __version__:
        line += f"  (latest: {latest} -- pip install --upgrade staso)"
    return line


def _check_latest_version() -> str | None:
    """Check PyPI for the latest staso version. Returns None on failure."""
    try:
        import httpx
        resp = httpx.get("https://pypi.org/pypi/staso/json", timeout=2.0)
        if resp.status_code == 200:
            return resp.json().get("info", {}).get("version")
    except Exception:
        pass
    return None


# -- setup command -------------------------------------------------------------


def _ensure_codex_hooks_enabled(scope: str) -> None:
    """Enable codex_hooks feature flag in Codex config.toml."""
    if scope == "global":
        config_path = Path.home() / ".codex" / "config.toml"
    else:
        config_path = Path(".codex") / "config.toml"

    config_path.parent.mkdir(parents=True, exist_ok=True)

    existing: dict = {}
    if config_path.exists():
        try:
            existing = tomllib.loads(config_path.read_text(encoding="utf-8"))
        except (tomllib.TOMLDecodeError, OSError):
            existing = {}

    features = existing.get("features", {})
    if features.get("codex_hooks") is True:
        return

    # Rebuild TOML preserving existing keys
    features["codex_hooks"] = True
    existing["features"] = features
    config_path.write_text(_dict_to_toml(existing), encoding="utf-8")


def _dict_to_toml(data: dict) -> str:
    """Minimal TOML serializer for flat/one-level-nested dicts."""
    lines: list[str] = []
    # Top-level scalars first
    for key, value in data.items():
        if not isinstance(value, dict):
            lines.append(f"{_toml_key(key)} = {_toml_value(value)}")
    # Then tables
    for key, value in data.items():
        if isinstance(value, dict):
            lines.append(f"\n[{_toml_key(key)}]")
            for k, v in value.items():
                lines.append(f"{_toml_key(k)} = {_toml_value(v)}")
    lines.append("")
    return "\n".join(lines)


_BARE_KEY_RE = __import__("re").compile(r"^[A-Za-z0-9_-]+$")


def _toml_key(key: str) -> str:
    """Quote TOML keys that contain characters outside A-Za-z0-9_-."""
    if _BARE_KEY_RE.match(key):
        return key
    return f'"{key}"'


def _toml_value(v: object) -> str:
    if isinstance(v, bool):
        return "true" if v else "false"
    if isinstance(v, str):
        return f'"{v}"'
    if isinstance(v, (int, float)):
        return str(v)
    if isinstance(v, dict):
        pairs = ", ".join(f"{_toml_key(k)} = {_toml_value(val)}" for k, val in v.items())
        return f"{{ {pairs} }}"
    return f'"{v}"'


def _resolve_settings_path(agent: AgentConfig, scope: str) -> Path:
    if scope == "global":
        return Path.home() / agent.global_settings
    return Path(agent.project_settings)


def _is_interactive_setup(args: argparse.Namespace) -> bool:
    """Check if setup was called without the required --api-key flag."""
    has_api_key = bool(getattr(args, "api_key", None) or os.environ.get("STASO_API_KEY", ""))
    return not has_api_key and sys.stdin.isatty()


def cmd_setup(args: argparse.Namespace) -> int:
    """Write hook configuration for a CLI agent to the chosen settings file."""
    # Launch interactive wizard when no API key provided and terminal is a TTY
    if _is_interactive_setup(args):
        from staso.interactive import interactive_setup

        result = interactive_setup()
        if result is None:
            print("\nSetup cancelled.")
            return 1

        # Map wizard results back to args
        args.target = result["target"]
        args.api_key = result["api_key"]
        args.workspace = result["workspace"]
        args.environment = result["environment"]
        args.agent_id = result["agent_id"]
        args.scope = result["scope"]
        args.auto_sync = result["auto_sync"]
        if not getattr(args, "base_url", None):
            args.base_url = None

    agent_name = getattr(args, "target", None) or "claude-code"
    agent = get_agent(agent_name)
    if agent is None:
        available = ", ".join(sorted(_AGENTS.keys()))
        print(f"error: unknown agent '{agent_name}'. Available: {available}", file=sys.stderr)
        return 1

    api_key = args.api_key or os.environ.get("STASO_API_KEY", "")
    if not api_key:
        print(
            "error: --api-key is required (or set STASO_API_KEY env var)",
            file=sys.stderr,
        )
        return 1

    python = sys.executable
    env_vars: dict[str, str] = {"STASO_API_KEY": api_key}
    if args.base_url:
        env_vars["STASO_BASE_URL"] = args.base_url
    if args.workspace:
        env_vars["STASO_WORKSPACE_SLUG"] = args.workspace
    if args.environment:
        env_vars["STASO_ENVIRONMENT"] = args.environment
    if args.agent_id:
        env_vars["STASO_AGENT_ID"] = args.agent_id
    if getattr(args, "auto_sync", False):
        env_vars["STASO_AUTO_SYNC"] = "1"

    if agent.embed_env_in_command:
        env_prefix = " ".join(f"{k}={v}" for k, v in env_vars.items())
        command = f"{env_prefix} {python} -m staso.{agent.module}"
        settings_env: dict[str, str] = {}
    else:
        command = f"{python} -m staso.{agent.module}"
        settings_env = env_vars

    hooks = _build_hooks_config(command, agent)

    settings_path = _resolve_settings_path(agent, args.scope)

    settings_path.parent.mkdir(parents=True, exist_ok=True)
    existing: dict = {}
    if settings_path.exists():
        try:
            existing = json.loads(settings_path.read_text(encoding="utf-8"))
        except (json.JSONDecodeError, OSError):
            print(
                f"warning: could not read existing {settings_path}, starting fresh",
                file=sys.stderr,
            )

    merged = _merge_settings(existing, hooks, settings_env)
    settings_path.write_text(json.dumps(merged, indent=2), encoding="utf-8")

    # Agent-specific post-setup
    if agent.name == "codex":
        _ensure_codex_hooks_enabled(args.scope)

    scope_label = f"~/{agent.global_settings}" if args.scope == "global" else agent.project_settings
    print()
    print(f"  \033[92m\u2713\033[0m \033[1mStaso {agent.display_name} hooks configured\033[0m")
    print(f"    Settings: {scope_label}")
    print(f"    Python:   {python}")
    print(f"    API key:  {api_key[:8]}...")
    if args.workspace:
        print(f"    Workspace: {args.workspace}")
    if args.environment:
        print(f"    Environment: {args.environment}")
    if args.base_url:
        print(f"    Backend:  {args.base_url}")
    if getattr(args, "auto_sync", False):
        print(f"    Auto-sync: enabled")
    print()
    print(f"  Start a {agent.display_name} conversation to begin tracing.")
    print()
    return 0


# kept for backward compat
def cmd_setup_claude_code(args: argparse.Namespace) -> int:
    """Deprecated: use `staso setup --target claude-code` instead."""
    args.target = "claude-code"
    return cmd_setup(args)


# -- sync command --------------------------------------------------------------


def _friendly_path(path: Path) -> str:
    """Shorten a path for display — replace $HOME with ~."""
    home = str(Path.home())
    s = str(path)
    return s.replace(home, "~") if s.startswith(home) else s


def _sync_agent(agent_name: str, cwd: str) -> None:
    """Sync a single agent's hook config. Prints status."""
    from staso._common.repair import (
        _find_settings_with_staso_hooks,
        _settings_candidates,
        repair_hooks,
        sync_python_path,
    )

    agent = get_agent(agent_name)
    if agent is None:
        return

    candidates = _settings_candidates(agent, cwd)
    settings_path, _ = _find_settings_with_staso_hooks(candidates)
    if settings_path is None:
        return

    label = f"{agent.display_name} ({_friendly_path(settings_path)})"

    path_updated = sync_python_path(agent_name, cwd)
    hooks_synced = repair_hooks(agent_name, cwd)

    if path_updated:
        print(f"  {label}: Python path updated to {sys.executable}")
    if hooks_synced:
        print(f"  {label}: hook events synced.")
    if not path_updated and not hooks_synced:
        print(f"  {label}: already up to date.")


def _toggle_auto_sync(agent_name: str, cwd: str, enable: bool) -> None:
    """Enable or disable STASO_AUTO_SYNC in an agent's hook config."""
    from staso._common.repair import (
        _find_settings_with_staso_hooks,
        _settings_candidates,
    )

    agent = get_agent(agent_name)
    if agent is None:
        return

    candidates = _settings_candidates(agent, cwd)
    settings_path, existing = _find_settings_with_staso_hooks(candidates)
    if settings_path is None:
        print(f"No staso hooks found for {agent.display_name}.")
        return

    label = _friendly_path(settings_path)

    if agent.embed_env_in_command:
        # For Codex: add/remove STASO_AUTO_SYNC=1 in command strings
        hooks = existing.get("hooks", {})
        changed = False
        for event_entries in hooks.values():
            for entry in event_entries:
                if not _is_staso_hook(entry):
                    continue
                for h in entry.get("hooks", [entry]):
                    cmd = h.get("command", "")
                    has_it = "STASO_AUTO_SYNC=1" in cmd
                    if enable and not has_it:
                        h["command"] = f"STASO_AUTO_SYNC=1 {cmd}"
                        changed = True
                    elif not enable and has_it:
                        h["command"] = cmd.replace("STASO_AUTO_SYNC=1 ", "")
                        changed = True
        if changed:
            settings_path.write_text(json.dumps(existing, indent=2), encoding="utf-8")
    else:
        # For Claude Code: set in env section
        env = existing.get("env", {})
        if enable:
            env["STASO_AUTO_SYNC"] = "1"
        else:
            env.pop("STASO_AUTO_SYNC", None)
        existing["env"] = env
        settings_path.write_text(json.dumps(existing, indent=2), encoding="utf-8")

    state = "enabled" if enable else "disabled"
    print(f"  {agent.display_name} ({label}): auto-sync {state}.")


def cmd_sync(args: argparse.Namespace) -> int:
    """Sync hook configuration with the current package version."""
    from staso._common.repair import _find_settings_with_staso_hooks, _settings_candidates

    cwd = os.getcwd()
    target = getattr(args, "target", None)
    enable_auto = getattr(args, "enable_auto_sync", False)
    disable_auto = getattr(args, "disable_auto_sync", False)

    # Handle auto-sync toggle
    if enable_auto or disable_auto:
        targets = [target] if target else list(_AGENTS.keys())
        for name in targets:
            agent = get_agent(name)
            if agent is None:
                continue
            candidates = _settings_candidates(agent, cwd)
            settings_path, _ = _find_settings_with_staso_hooks(candidates)
            if settings_path is not None:
                _toggle_auto_sync(name, cwd, enable_auto)
        return 0

    # Normal sync
    if target:
        agent = get_agent(target)
        if agent is None:
            available = ", ".join(sorted(_AGENTS.keys()))
            print(f"error: unknown agent '{target}'. Available: {available}", file=sys.stderr)
            return 1
        candidates = _settings_candidates(agent, cwd)
        settings_path, _ = _find_settings_with_staso_hooks(candidates)
        if settings_path is None:
            print(f"No staso hooks found for {agent.display_name}. Run 'staso setup --target {target}' first.")
            return 0
        _sync_agent(target, cwd)
    else:
        found = False
        for name, agent in _AGENTS.items():
            candidates = _settings_candidates(agent, cwd)
            settings_path, _ = _find_settings_with_staso_hooks(candidates)
            if settings_path is not None:
                found = True
                _sync_agent(name, cwd)
        if not found:
            print("No staso hook configs found. Run 'staso setup' first.")

    return 0


# -- uninstall command ---------------------------------------------------------


def _remove_staso_hooks(settings_path: Path) -> dict:
    """Remove all Staso hook entries and env vars from a settings file.

    Returns the cleaned settings dict.
    """
    try:
        existing = json.loads(settings_path.read_text(encoding="utf-8"))
    except (json.JSONDecodeError, OSError):
        return {}

    # Remove Staso hook entries
    hooks = existing.get("hooks", {})
    for event in list(hooks.keys()):
        hooks[event] = [e for e in hooks[event] if not _is_staso_hook(e)]
        if not hooks[event]:
            del hooks[event]
    if hooks:
        existing["hooks"] = hooks
    else:
        existing.pop("hooks", None)

    # Remove Staso env vars
    env = existing.get("env", {})
    for key in list(env.keys()):
        if key.startswith("STASO_"):
            del env[key]
    if env:
        existing["env"] = env
    else:
        existing.pop("env", None)

    return existing


def _disable_codex_hooks_feature(scope: str) -> None:
    """Remove codex_hooks feature flag from Codex config.toml."""
    if scope == "global":
        config_path = Path.home() / ".codex" / "config.toml"
    else:
        config_path = Path(".codex") / "config.toml"

    if not config_path.exists():
        return

    try:
        existing = tomllib.loads(config_path.read_text(encoding="utf-8"))
    except (tomllib.TOMLDecodeError, OSError):
        return

    features = existing.get("features", {})
    if "codex_hooks" not in features:
        return

    del features["codex_hooks"]
    if features:
        existing["features"] = features
    else:
        existing.pop("features", None)

    config_path.write_text(_dict_to_toml(existing), encoding="utf-8")


def _clean_state_dir(agent_name: str) -> int:
    """Remove Staso state files for an agent. Returns count of files removed."""
    # State dirs use the agent name directly: ~/.staso/claude-code, ~/.staso/codex
    state_dir = Path.home() / ".staso" / agent_name
    if not state_dir.exists():
        return 0
    count = 0
    for f in state_dir.iterdir():
        try:
            if f.is_file():
                f.unlink()
                count += 1
            elif f.is_dir():
                f.rmdir()
                count += 1
        except OSError:
            pass
    try:
        state_dir.rmdir()
    except OSError:
        pass
    return count


def cmd_uninstall(args: argparse.Namespace) -> int:
    """Remove Staso hooks from agent settings and clean up state files."""
    from staso._common.repair import _find_settings_with_staso_hooks, _settings_candidates

    cwd = os.getcwd()
    target = getattr(args, "target", None)
    targets = [target] if target else list(_AGENTS.keys())

    any_found = False
    for agent_name in targets:
        agent = get_agent(agent_name)
        if agent is None:
            continue

        candidates = _settings_candidates(agent, cwd)
        settings_path, _ = _find_settings_with_staso_hooks(candidates)

        if settings_path is None:
            continue

        any_found = True
        label = _friendly_path(settings_path)

        # Remove hooks and env vars from settings
        cleaned = _remove_staso_hooks(settings_path)
        settings_path.write_text(json.dumps(cleaned, indent=2), encoding="utf-8")
        print(f"  {agent.display_name}: removed hooks from {label}")

        # Agent-specific cleanup
        if agent.name == "codex":
            _disable_codex_hooks_feature(
                "global" if str(Path.home()) in str(settings_path) else "project"
            )
            print(f"  {agent.display_name}: disabled codex_hooks feature flag")

        # Clean up state files
        count = _clean_state_dir(agent.name)
        if count:
            print(f"  {agent.display_name}: removed {count} state file(s)")

    if not any_found:
        print("No Staso hooks found. Nothing to uninstall.")

    return 0


# -- update command ------------------------------------------------------------


def cmd_update(args: argparse.Namespace) -> int:
    """Upgrade the Staso package and sync hook configuration."""
    import subprocess

    print("Upgrading staso...")
    result = subprocess.run(
        [sys.executable, "-m", "pip", "install", "--upgrade", "staso"],
        capture_output=True,
        text=True,
    )
    if result.returncode != 0:
        print(f"error: pip upgrade failed:\n{result.stderr.strip()}", file=sys.stderr)
        return 1

    # Show new version
    from staso._version import __version__
    print(f"  Installed: staso {__version__}")

    # Sync hooks
    print("Syncing hooks...")
    sync_args = argparse.Namespace(target=None, enable_auto_sync=False, disable_auto_sync=False)
    cmd_sync(sync_args)
    return 0


# -- status command ------------------------------------------------------------


def cmd_status(args: argparse.Namespace) -> int:
    """Show current Staso hook configuration status."""
    from staso._common.repair import _find_settings_with_staso_hooks, _settings_candidates
    from staso._version import __version__

    print(f"staso {__version__}")
    print()

    cwd = os.getcwd()
    target = getattr(args, "target", None)
    targets = [target] if target else list(_AGENTS.keys())

    any_found = False
    for agent_name in targets:
        agent = get_agent(agent_name)
        if agent is None:
            if target:
                available = ", ".join(sorted(_AGENTS.keys()))
                print(f"error: unknown agent '{target}'. Available: {available}", file=sys.stderr)
                return 1
            continue

        candidates = _settings_candidates(agent, cwd)
        settings_path, existing = _find_settings_with_staso_hooks(candidates)

        if settings_path is None:
            print(f"  {agent.display_name}: not configured")
            continue

        any_found = True
        label = _friendly_path(settings_path)
        hooks = existing.get("hooks", {})

        # Count Staso hook events
        staso_events = [
            event for event, entries in hooks.items()
            if any(_is_staso_hook(e) for e in entries)
        ]

        print(f"  {agent.display_name}: {len(staso_events)} hook events in {label}")

        # Show env/config details
        if agent.embed_env_in_command:
            # Check for auto-sync in command
            for entries in hooks.values():
                for entry in entries:
                    if not _is_staso_hook(entry):
                        continue
                    for h in entry.get("hooks", [entry]):
                        cmd = h.get("command", "")
                        if "STASO_AUTO_SYNC=1" in cmd:
                            print(f"    auto-sync: enabled")
                            break
                    break
                break
        else:
            env = existing.get("env", {})
            if env.get("STASO_AUTO_SYNC") == "1":
                print(f"    auto-sync: enabled")
            workspace = env.get("STASO_WORKSPACE_SLUG", "")
            if workspace:
                print(f"    workspace: {workspace}")
            environment = env.get("STASO_ENVIRONMENT", "")
            if environment:
                print(f"    environment: {environment}")

    if not any_found and not target:
        print("  No agents configured. Run 'staso setup' first.")

    return 0


# -- version command -----------------------------------------------------------


def cmd_version(_args: argparse.Namespace) -> int:
    """Print version information."""
    print(_version_string())
    return 0


# -- parser --------------------------------------------------------------------


def _add_setup_args(parser: argparse.ArgumentParser) -> None:
    """Add common setup arguments to a parser."""
    parser.add_argument("--api-key", metavar="KEY", help="Staso API key (ak_...)")
    parser.add_argument("--base-url", metavar="URL", help="Staso backend URL")
    parser.add_argument(
        "--workspace",
        metavar="SLUG",
        default="default",
        help="Workspace slug (default: default)",
    )
    parser.add_argument(
        "--environment",
        metavar="ENV",
        default="default",
        help="Environment name (default: default)",
    )
    parser.add_argument("--agent-id", metavar="ID", help="Agent ID registered in Staso")
    parser.add_argument(
        "--scope",
        choices=["global", "project"],
        default="global",
        help="Write to global or project settings",
    )
    parser.add_argument(
        "--auto-sync",
        action="store_true",
        help="Auto-sync hook config on each session start",
    )


def _build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="staso",
        description="Staso CLI",
    )
    parser.add_argument("--version", action="version", version=_version_string())
    sub = parser.add_subparsers(dest="command")

    # Primary: staso setup --target <name>
    setup = sub.add_parser(
        "setup",
        help="Configure hooks for a CLI AI agent to send traces to Staso",
    )
    setup.add_argument(
        "--target",
        choices=sorted(_AGENTS.keys()),
        default="claude-code",
        help="Which CLI tool to configure (default: claude-code)",
    )
    _add_setup_args(setup)

    # Sync: staso sync [--target <name>]
    sync = sub.add_parser(
        "sync",
        help="Sync hook config — add missing events, fix python path",
    )
    sync.add_argument(
        "--target",
        choices=sorted(_AGENTS.keys()),
        default=None,
        help="Which CLI tool to sync (default: all configured agents)",
    )
    auto_group = sync.add_mutually_exclusive_group()
    auto_group.add_argument(
        "--enable-auto-sync",
        action="store_true",
        help="Enable auto-sync on each session start",
    )
    auto_group.add_argument(
        "--disable-auto-sync",
        action="store_true",
        help="Disable auto-sync",
    )

    # Uninstall: staso uninstall [--target <name>]
    uninstall = sub.add_parser(
        "uninstall",
        help="Remove Staso hooks and clean up state files",
    )
    uninstall.add_argument(
        "--target",
        choices=sorted(_AGENTS.keys()),
        default=None,
        help="Which CLI tool to uninstall from (default: all configured agents)",
    )

    # Update: staso update
    sub.add_parser(
        "update",
        help="Upgrade staso package and sync hook configuration",
    )

    # Status: staso status [--target <name>]
    status = sub.add_parser(
        "status",
        help="Show current Staso hook configuration status",
    )
    status.add_argument(
        "--target",
        choices=sorted(_AGENTS.keys()),
        default=None,
        help="Which CLI tool to check (default: all agents)",
    )

    # Version: staso version
    sub.add_parser(
        "version",
        help="Show version and check for updates",
    )

    # Deprecated alias: staso setup-claude-code
    setup_cc = sub.add_parser(
        "setup-claude-code",
        help="(deprecated) Use 'staso setup --target claude-code' instead",
    )
    _add_setup_args(setup_cc)

    return parser


def main() -> None:
    parser = _build_parser()
    args = parser.parse_args()

    if args.command == "setup":
        sys.exit(cmd_setup(args))
    elif args.command == "uninstall":
        sys.exit(cmd_uninstall(args))
    elif args.command == "sync":
        sys.exit(cmd_sync(args))
    elif args.command == "update":
        sys.exit(cmd_update(args))
    elif args.command == "status":
        sys.exit(cmd_status(args))
    elif args.command == "version":
        sys.exit(cmd_version(args))
    elif args.command == "setup-claude-code":
        warnings.warn(
            "setup-claude-code is deprecated, use: staso setup --target claude-code",
            DeprecationWarning,
            stacklevel=1,
        )
        sys.exit(cmd_setup_claude_code(args))
    else:
        parser.print_help()
        sys.exit(0)
