"""CLI argument parser definitions."""

from __future__ import annotations

import argparse
from importlib.metadata import version
from typing import Callable


BoolConverter = Callable[[str], bool]


def _parse_bool(value: str) -> bool:
    """Convert CLI boolean input to a Python bool."""
    return str(value).lower() == "true"


def add_bool_argument(
    parser: argparse.ArgumentParser,
    name: str,
    default: bool,
    help_text: str,
    *,
    converter: BoolConverter = _parse_bool,
) -> None:
    """Add a CLI boolean flag that accepts explicit true or false values."""
    parser.add_argument(
        name,
        type=converter,
        choices=[True, False],
        default=default,
        metavar="{true,false}",
        help=f"{help_text} (default: {str(default).lower()})",
    )


def create_root_parser() -> argparse.ArgumentParser:
    """Create the root parser with global options."""
    parser = argparse.ArgumentParser(
        prog="stata-mcp",
        description="Stata-MCP command line interface",
        add_help=True,
    )
    parser.add_argument(
        "-v",
        "--version",
        action="version",
        version=f"%(prog)s {version('stata-mcp')}",
        help="show version information",
    )
    parser.add_argument(
        "-t",
        "--transport",
        choices=["stdio", "sse", "http"],
        default="stdio",
        help="MCP server transport method (default: stdio)",
    )
    parser.add_argument(
        "-u",
        "--usable",
        action="store_true",
        help="Check whether Stata-MCP can be used on this computer",
    )
    return parser


def add_agent_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    """Add the agent subcommand parser."""
    agent_parser = subparsers.add_parser("agent", help="Run Stata-MCP as agent mode")
    agent_subparsers = agent_parser.add_subparsers(dest="agent_action")

    agent_run_parser = agent_subparsers.add_parser("run", help="Start agent")
    agent_run_parser.add_argument(
        "--work-dir",
        default="./",
        help="Working directory for agent (default: current directory)",
    )
    return agent_parser


def add_tool_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    """Add the tool subcommand parser."""
    tool_parser = subparsers.add_parser("tool", help="Run local Stata tools through the API module")
    tool_subparsers = tool_parser.add_subparsers(dest="tool_action")

    tool_ado_install_parser = tool_subparsers.add_parser(
        "ado-install",
        help="Install an ado package through the API module",
    )
    tool_ado_install_parser.add_argument("package_name", help="Ado package name")
    tool_ado_install_parser.add_argument(
        "--source",
        choices=["ssc", "net", "github"],
        default="ssc",
        help="Package source (default: ssc)",
    )
    tool_ado_install_parser.add_argument(
        "--package-source-from",
        default=None,
        help="Net install source URL used when --source net",
    )
    add_bool_argument(
        tool_ado_install_parser,
        "--is-replace",
        default=True,
        help_text="Replace existing package files when supported",
    )

    tool_do_parser = tool_subparsers.add_parser("do", help="Run a do-file through the API module")
    tool_do_parser.add_argument("dofile_path", help="Path to the do-file")
    tool_do_parser.add_argument(
        "--log-file-name",
        default=None,
        help="Optional log file name without extension",
    )
    add_bool_argument(
        tool_do_parser,
        "--is-read-log",
        default=True,
        help_text="Read log content after execution",
    )
    add_bool_argument(
        tool_do_parser,
        "--is-replace-log",
        default=True,
        help_text="Replace the existing log file",
    )
    add_bool_argument(
        tool_do_parser,
        "--enable-smcl",
        default=True,
        help_text="Generate the SMCL log file",
    )

    tool_help_parser = tool_subparsers.add_parser(
        "help",
        help="Read Stata help output through the API module",
    )
    tool_help_parser.add_argument("stata_command", help="Stata command name")
    add_bool_argument(
        tool_help_parser,
        "--is-read-log",
        default=True,
        help_text="Read log content after execution",
    )
    add_bool_argument(
        tool_help_parser,
        "--enable-smcl",
        default=True,
        help_text="Generate the SMCL log file",
    )

    tool_data_info_parser = tool_subparsers.add_parser(
        "data-info",
        help="Read dataset metadata through the API module",
    )
    tool_data_info_parser.add_argument("data_path", help="Path to the data file")
    tool_data_info_parser.add_argument(
        "--encoding",
        default="utf-8",
        help="Text encoding for supported text-based data files (default: utf-8)",
    )
    tool_data_info_parser.add_argument(
        "--vars-list",
        nargs="+",
        default=None,
        help="Optional variable names to inspect",
    )

    tool_read_log_parser = tool_subparsers.add_parser(
        "read-log",
        help="Read a Stata log through the API module",
    )
    tool_read_log_parser.add_argument("file_path", help="Path to the log file")
    tool_read_log_parser.add_argument(
        "--encoding",
        default="utf-8",
        help="Log file encoding (default: utf-8)",
    )
    tool_read_log_parser.add_argument(
        "--output-format",
        choices=["full", "core", "dict"],
        default="core",
        help="Output format for supported .log and .smcl files (default: core)",
    )
    return tool_parser


def add_config_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    """Add the config subcommand parser."""
    config_parser = subparsers.add_parser("config", help="Show and manage Stata-MCP configuration")
    config_subparsers = config_parser.add_subparsers(dest="config_target")

    config_cli_parser = config_subparsers.add_parser("cli", help="Manage Stata CLI executable path")
    config_cli_subparsers = config_cli_parser.add_subparsers(dest="config_cli_action")

    config_cli_set_parser = config_cli_subparsers.add_parser(
        "set",
        help="Set STATA_CLI path in config file",
    )
    config_cli_set_parser.add_argument(
        "value",
        nargs="?",
        default=None,
        help="Optional STATA_CLI path. If omitted, auto-detect from StataFinder.",
    )
    return config_parser


def add_install_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    """Add the install subcommand parser."""
    install_parser = subparsers.add_parser("install", help="Install Stata-MCP to MCP clients")
    install_parser.add_argument(
        "-c",
        "--client",
        choices=["claude", "cc", "gemini", "cursor", "cline", "codex", "opencode"],
        default="claude",
        help="Target client (default: claude)",
    )
    install_parser.add_argument(
        "-a",
        "--all",
        action="store_true",
        help="Install to all supported clients",
    )
    install_parser.add_argument(
        "--json-file",
        type=str,
        help="Custom target client config file path",
    )
    return install_parser


def add_sandbox_parser(subparsers: argparse._SubParsersAction) -> argparse.ArgumentParser:
    """Add the sandbox-install subcommand parser."""
    sandbox_parser = subparsers.add_parser(
        "sandbox-install",
        help="Install Docker-based Stata-MCP to MCP client",
    )
    sandbox_parser.add_argument(
        "-c",
        "--client",
        choices=["claude", "cc", "claude-code", "gemini", "cursor", "cline", "codex", "opencode"],
        default="claude",
        help="Target client (default: claude)",
    )
    sandbox_parser.add_argument(
        "-l",
        "--license-file",
        required=True,
        help="Path to Stata license file (stata.lic)",
    )
    sandbox_parser.add_argument(
        "--work-dir",
        default="./",
        help="Working directory for Stata operations (default: current directory)",
    )
    sandbox_parser.add_argument(
        "--cpus",
        type=float,
        default=None,
        help="CPU core limit for container (e.g., 2.0)",
    )
    sandbox_parser.add_argument(
        "--memory",
        type=str,
        default=None,
        help="Memory limit for container (e.g., 4g, 512m)",
    )
    sandbox_parser.add_argument(
        "-V",
        "--version",
        choices=["19_5", "18_5", "18"],
        default="19_5",
        help="Stata version (default: 19_5)",
    )
    sandbox_parser.add_argument(
        "-e",
        "--edition",
        choices=["mp", "se", "be"],
        default="mp",
        help="Stata edition: mp (Multi-processor), se (Standard), be (Basic) (default: mp)",
    )
    sandbox_parser.add_argument(
        "--tag",
        default="latest",
        help="Docker image tag (default: latest)",
    )
    sandbox_parser.add_argument(
        "-s",
        "--source",
        choices=["github", "docker"],
        default="github",
        help="Docker image registry source: github (ghcr.io) or docker (DockerHub) (default: github)",
    )
    return sandbox_parser
