"""``ilum deps`` subcommands — dependency management."""

from __future__ import annotations

import shutil
import subprocess

import typer

import ilum.cli.output as output_mod
from ilum.doctor.checks import CheckStatus, check_binary
from ilum.errors import PrerequisiteError
from ilum.wizard.deps import TOOL_REGISTRY, _detect_platform, _install_tool

deps_app = typer.Typer(help="Manage CLI dependencies (helm, kubectl, docker, k3d, etc.).")

_CORE_TOOLS = ["helm", "kubectl", "docker"]
_VALID_PROVIDERS = {"k3d", "minikube", "kind"}


@deps_app.command()
def install(
    tools: list[str] = typer.Argument(  # noqa: B008
        None, help="Tools to install (default: all core + provider)."
    ),
    provider: str = typer.Option("k3d", help="Cluster provider: k3d, minikube, kind."),
    dry_run: bool = typer.Option(False, "--dry-run", help="Preview without executing."),
) -> None:
    """Install missing CLI dependencies."""
    console = output_mod.console

    # Validate provider
    if provider not in _VALID_PROVIDERS:
        console.error(
            f"Unknown provider '{provider}'. Choose from: {', '.join(sorted(_VALID_PROVIDERS))}"
        )
        raise typer.Exit(code=1)

    # Determine which tools to install
    if tools:
        for name in tools:
            if name not in TOOL_REGISTRY:
                console.error(
                    f"Unknown tool '{name}'. Known tools: {', '.join(sorted(TOOL_REGISTRY))}"
                )
                raise typer.Exit(code=1)
        target_tools = tools
    else:
        target_tools = [*_CORE_TOOLS, provider]

    plat = _detect_platform()
    installed = 0
    skipped = 0
    failed = 0

    for name in target_tools:
        tool = TOOL_REGISTRY[name]
        result = check_binary(name, tool.min_version)

        if result.status == CheckStatus.OK:
            console.success(f"{name} already installed ({result.message})")
            skipped += 1
            continue

        if dry_run:
            console.info(f"Would install {name} ({result.message})")
            continue

        console.info(f"Installing {name}...")
        try:
            _install_tool(name, plat, console)
        except (subprocess.CalledProcessError, OSError, PrerequisiteError) as exc:
            console.error(f"Failed to install {name}: {exc}")
            failed += 1
            continue

        # Re-check after install
        recheck = check_binary(name, tool.min_version)
        if recheck.status == CheckStatus.OK:
            console.success(f"{name} installed successfully ({recheck.message})")
            installed += 1
        else:
            console.warning(f"{name} installed but version check failed: {recheck.message}")
            failed += 1

    if dry_run:
        console.info("Dry-run mode — no changes applied.")
        return

    # Summary
    parts: list[str] = []
    if installed:
        parts.append(f"{installed} installed")
    if skipped:
        parts.append(f"{skipped} already present")
    if failed:
        parts.append(f"{failed} failed")
    if parts:
        console.info(f"Summary: {', '.join(parts)}.")

    if failed:
        raise typer.Exit(code=1)


@deps_app.command("list")
def list_deps() -> None:
    """List CLI dependencies and their status."""
    console = output_mod.console

    from ilum.cli.formatters import CommandResult, OutputFormat, ResultFormatter

    fmt = OutputFormat(console.output_format)

    rows: list[list[str]] = []
    data_list: list[dict[str, str]] = []
    for name, tool in TOOL_REGISTRY.items():
        result = check_binary(name, tool.min_version)
        path = shutil.which(name) or "\u2014"

        if result.status == CheckStatus.OK:
            status_str = "[green]\u2713 OK[/green]"
            status_plain = "ok"
            version_str = result.message
        elif result.status == CheckStatus.FAIL:
            if "not found" in result.message:
                status_str = "[red]\u2717 Missing[/red]"
                status_plain = "missing"
                version_str = "\u2014"
                path = "\u2014"
            else:
                status_str = "[yellow]! Outdated[/yellow]"
                status_plain = "outdated"
                version_str = result.message
        else:
            status_str = "[dim]\u2013 Unknown[/dim]"
            status_plain = "unknown"
            version_str = result.message

        rows.append([name, status_str, version_str, path])
        data_list.append(
            {"name": name, "status": status_plain, "version": version_str, "path": path}
        )

    if fmt != OutputFormat.TABLE:
        cmd_result = CommandResult(data=data_list, summary=f"{len(data_list)} dependencies")
        ResultFormatter().format(cmd_result, fmt, console)
        return

    console.table(
        "Ilum Dependencies",
        ["Tool", "Status", "Version", "Path"],
        rows,
    )
