"""CLI entry point and step orchestration using argparse."""

from __future__ import annotations

import argparse
import subprocess
import sys
from pathlib import Path

from installer import __build__
from installer.config import load_config, save_config
from installer.context import InstallContext
from installer.errors import FatalInstallError, InstallationCancelled
from installer.steps.base import BaseStep
from installer.steps.claude_files import ClaudeFilesStep
from installer.steps.config_files import ConfigFilesStep
from installer.steps.dependencies import DependenciesStep
from installer.steps.finalize import FinalizeStep
from installer.steps.prerequisites import PrerequisitesStep
from installer.steps.project_init import ProjectInitStep
from installer.steps.shell_config import ShellConfigStep
from installer.steps.vscode_extensions import VSCodeExtensionsStep
from installer.ui import Console


def get_all_steps() -> list[BaseStep]:
    """Get all installation steps in order."""
    return [
        PrerequisitesStep(),
        ClaudeFilesStep(),
        ConfigFilesStep(),
        DependenciesStep(),
        ShellConfigStep(),
        VSCodeExtensionsStep(),
        ProjectInitStep(),
        FinalizeStep(),
    ]


def run_installation(ctx: InstallContext) -> None:
    """Execute all installation steps."""
    ui = ctx.ui
    steps = get_all_steps()

    if ui:
        ui.set_total_steps(len(steps))

    for step in steps:
        if ui:
            ui.step(step.name.replace("_", " ").title())

        if step.check(ctx):
            if ui:
                ui.info(f"Already complete, skipping")
            continue

        try:
            step.run(ctx)
        except KeyboardInterrupt:
            raise InstallationCancelled(step.name) from None
        ctx.mark_completed(step.name)


def _prompt_for_features(
    console: Console,
    saved_config: dict,
    skip_python: bool,
    skip_typescript: bool,
    skip_golang: bool,
    skip_prompts: bool,
) -> tuple[bool, bool, bool]:
    """Prompt for feature installation preferences. Returns (python, typescript, golang)."""
    enable_python = not skip_python
    if not skip_python:
        if "enable_python" in saved_config:
            enable_python = saved_config["enable_python"]
            if not skip_prompts:
                console.print()
                console.print(f"  [dim]Using saved preference: Python support = {enable_python}[/dim]")
        elif not skip_prompts:
            console.print()
            console.print("  [bold]Do you want to install advanced Python features?[/bold]")
            console.print("  This includes: uv, ruff, basedpyright, and Python quality hooks")
            enable_python = console.confirm("Install Python support?", default=True)
        else:
            enable_python = False

    enable_typescript = not skip_typescript
    if not skip_typescript:
        if "enable_typescript" in saved_config:
            enable_typescript = saved_config["enable_typescript"]
            if not skip_prompts:
                console.print(f"  [dim]Using saved preference: TypeScript support = {enable_typescript}[/dim]")
        elif not skip_prompts:
            console.print()
            console.print("  [bold]Do you want to install TypeScript features?[/bold]")
            console.print("  This includes: TypeScript quality hooks (eslint, tsc, prettier)")
            enable_typescript = console.confirm("Install TypeScript support?", default=True)
        else:
            enable_typescript = False

    enable_golang = not skip_golang
    if not skip_golang:
        if "enable_golang" in saved_config:
            enable_golang = saved_config["enable_golang"]
            if not skip_prompts:
                console.print(f"  [dim]Using saved preference: Go support = {enable_golang}[/dim]")
        elif not skip_prompts:
            console.print()
            console.print("  [bold]Do you want to install Go features?[/bold]")
            console.print("  This includes: Go quality hooks (gofmt, go vet, golangci-lint)")
            enable_golang = console.confirm("Install Go support?", default=True)
        else:
            enable_golang = False

    return enable_python, enable_typescript, enable_golang


def cmd_install(args: argparse.Namespace) -> int:
    """Install Tribunal."""
    # Headless/CI mode: --headless or --yes implies non-interactive, no Rich UI
    headless = getattr(args, "headless", False) or getattr(args, "yes", False)
    skip_access_check = getattr(args, "skip_access_check", False)

    if headless:
        # Plain print, no Rich console
        import builtins
        non_interactive = True
        quiet = True
    else:
        non_interactive = args.non_interactive
        quiet = args.quiet

    console = Console(non_interactive=non_interactive or headless, quiet=quiet or headless)

    effective_local_repo_dir = args.local_repo_dir if args.local_repo_dir else (Path.cwd() if args.local else None)
    skip_prompts = non_interactive or headless
    project_dir = Path.cwd()
    saved_config = load_config()

    if headless:
        print("[headless] Tribunal installation starting (CI/headless mode)")
    else:
        console.banner()

    enable_python, enable_typescript, enable_golang = _prompt_for_features(
        console, saved_config, args.skip_python, args.skip_typescript, args.skip_golang, skip_prompts
    )

    if not skip_prompts:
        saved_config["enable_python"] = enable_python
        saved_config["enable_typescript"] = enable_typescript
        saved_config["enable_golang"] = enable_golang
        save_config(saved_config)

    ctx = InstallContext(
        project_dir=project_dir,
        enable_python=enable_python,
        enable_typescript=enable_typescript,
        enable_golang=enable_golang,
        non_interactive=non_interactive or headless,
        skip_env=args.skip_env or headless,
        local_mode=args.local,
        local_repo_dir=effective_local_repo_dir,
        is_local_install=args.local_system,
        target_version=args.target_version,
        ui=console,
        skip_access_check=skip_access_check or headless,
    )

    try:
        run_installation(ctx)
    except FatalInstallError as e:
        console.error(f"Installation failed: {e}")
        return 1
    except InstallationCancelled as e:
        console.warning(f"Installation cancelled during: {e.step_name}")
        console.info("Run the installer again to resume from where you left off")
        return 130
    except KeyboardInterrupt:
        console.warning("Installation cancelled")
        return 130

    return 0


def cmd_version(_args: argparse.Namespace) -> int:
    """Show version information."""
    print(f"tribunal-installer (build: {__build__})")
    return 0


def find_tribunal_binary() -> Path | None:
    """Find the tribunal binary in ~/.tribunal/bin/."""
    binary_path = Path.home() / ".tribunal" / "bin" / "tribunal"
    if binary_path.exists():
        return binary_path
    return None


def cmd_launch(args: argparse.Namespace) -> int:
    """Launch Claude Code via tribunal binary."""
    claude_args = args.args or []

    sf_path = find_tribunal_binary()
    if sf_path:
        cmd = [str(sf_path)] + claude_args
    else:
        cmd = ["claude"] + claude_args

    return subprocess.call(cmd)


def create_parser() -> argparse.ArgumentParser:
    """Create the argument parser."""
    parser = argparse.ArgumentParser(
        prog="installer",
        description="Tribunal Installer",
    )
    subparsers = parser.add_subparsers(dest="command", help="Available commands")

    install_parser = subparsers.add_parser("install", help="Install Tribunal")
    install_parser.add_argument(
        "-n",
        "--non-interactive",
        action="store_true",
        help="Run without interactive prompts",
    )
    install_parser.add_argument(
        "-q",
        "--quiet",
        action="store_true",
        help="Minimal output (for updates)",
    )
    install_parser.add_argument(
        "--skip-env",
        action="store_true",
        help="Skip environment setup (API keys)",
    )
    install_parser.add_argument(
        "--local",
        action="store_true",
        help="Use local files instead of downloading",
    )
    install_parser.add_argument(
        "--local-repo-dir",
        type=Path,
        default=None,
        help="Local repository directory",
    )
    install_parser.add_argument(
        "--skip-python",
        action="store_true",
        help="Skip Python support installation",
    )
    install_parser.add_argument(
        "--skip-typescript",
        action="store_true",
        help="Skip TypeScript support installation",
    )
    install_parser.add_argument(
        "--skip-golang",
        action="store_true",
        help="Skip Go support installation",
    )
    install_parser.add_argument(
        "--local-system",
        action="store_true",
        help="Local installation (not in container)",
    )
    install_parser.add_argument(
        "--target-version",
        type=str,
        default=None,
        help="Target version/tag for downloads",
    )
    install_parser.add_argument(
        "--headless",
        action="store_true",
        help="Headless/CI mode: skip Rich UI, use plain print, skip prompts (use defaults).",
    )
    install_parser.add_argument(
        "--yes",
        "-y",
        action="store_true",
        help="Auto-confirm all prompts (implies headless defaults).",
    )
    install_parser.add_argument(
        "--skip-access-check",
        action="store_true",
        help="Skip Claude API access check during installation.",
    )

    subparsers.add_parser("version", help="Show version information")

    launch_parser = subparsers.add_parser("launch", help="Launch Claude Code")
    launch_parser.add_argument(
        "args",
        nargs="*",
        help="Arguments to pass to claude",
    )

    return parser


def main() -> None:
    """Main entry point."""
    parser = create_parser()
    args = parser.parse_args()

    if args.command == "install":
        sys.exit(cmd_install(args))
    elif args.command == "version":
        sys.exit(cmd_version(args))
    elif args.command == "launch":
        sys.exit(cmd_launch(args))
    else:
        parser.print_help()
        sys.exit(0)


if __name__ == "__main__":
    main()
