"""``ilum cluster`` sub-commands for local Kubernetes cluster management."""

from __future__ import annotations

import questionary
import typer

from ilum.cli.output import console
from ilum.config.manager import ConfigManager
from ilum.config.paths import IlumPaths
from ilum.errors import IlumError, PrerequisiteError
from ilum.wizard.cluster import PRESETS, ClusterManager, ClusterProvider

cluster_app = typer.Typer(help="Manage local Kubernetes clusters.")


def _is_interactive() -> bool:
    """Return True when stdin is a terminal (safe to prompt the user)."""
    import sys

    return sys.stdin.isatty()


def _provider_from_str(value: str) -> ClusterProvider:
    try:
        return ClusterProvider(value.lower())
    except ValueError:
        raise typer.BadParameter(
            f"Unknown provider '{value}'. Choose from: minikube, k3d, kind."
        ) from None


def _prompt_provider() -> str:
    """Interactively ask the user to pick a cluster provider."""
    answer: str | None = questionary.select(
        "Cluster provider:",
        choices=["k3d", "minikube", "kind"],
    ).ask()
    if answer is None:
        raise typer.Exit(code=130)
    return answer


def _prompt_preset() -> str:
    """Interactively ask the user to pick a resource preset."""
    answer: str | None = questionary.select(
        "Resource preset:",
        choices=[
            questionary.Choice(
                title=f"{k} (CPUs: {v.cpus}, Memory: {v.memory})",
                value=k,
            )
            for k, v in PRESETS.items()
        ],
    ).ask()
    if answer is None:
        raise typer.Exit(code=130)
    return answer


@cluster_app.command()
def create(
    provider: str = typer.Option("", help="Cluster provider: minikube, k3d, kind."),
    preset: str = typer.Option("", help="Resource preset: dev, full."),
    name: str = typer.Option("", help="Cluster name (default: from preset)."),
) -> None:
    """Create a local Kubernetes cluster."""
    if not provider:
        provider = _prompt_provider() if _is_interactive() else "k3d"
    prov = _provider_from_str(provider)

    if not preset:
        preset = _prompt_preset() if _is_interactive() else "dev"

    if preset not in PRESETS:
        console.error(f"Unknown preset '{preset}'. Choose from: {', '.join(PRESETS)}")
        raise typer.Exit(code=1)

    preset_config = PRESETS[preset]
    mgr = ClusterManager()

    try:
        record = mgr.create(prov, preset_config, console, name=name)
    except (PrerequisiteError, IlumError) as exc:
        console.handle_error(exc)
        raise typer.Exit(code=1) from None
    except Exception as exc:
        console.error(f"Cluster creation failed: {exc}")
        raise typer.Exit(code=1) from None

    # Persist the cluster record
    paths = IlumPaths.default()
    config_mgr = ConfigManager(paths)
    config = config_mgr.ensure_config()
    config.clusters.append(record)
    config_mgr.save(config)

    console.info(f"Kubecontext: {record.kubecontext}")
    console.info("Run 'ilum init' or 'ilum install' to deploy Ilum on this cluster.")


@cluster_app.command()
def delete(
    name: str = typer.Argument(..., help="Cluster name to delete."),
) -> None:
    """Delete a local Kubernetes cluster."""
    paths = IlumPaths.default()
    config_mgr = ConfigManager(paths)
    config = config_mgr.ensure_config()

    # Find the cluster record
    record = None
    for r in config.clusters:
        if r.name == name:
            record = r
            break

    if record is None:
        console.error(f"Cluster '{name}' not found in config. Known clusters:")
        for r in config.clusters:
            console.info(f"  {r.name} ({r.provider})")
        raise typer.Exit(code=1)

    prov = _provider_from_str(record.provider)
    mgr = ClusterManager()

    try:
        mgr.delete(prov, name, console)
    except (PrerequisiteError, IlumError) as exc:
        console.handle_error(exc)
        raise typer.Exit(code=1) from None
    except Exception as exc:
        console.error(f"Cluster deletion failed: {exc}")
        raise typer.Exit(code=1) from None

    # Remove from config
    config.clusters = [r for r in config.clusters if r.name != name]
    config_mgr.save(config)


@cluster_app.command("list")
def list_clusters() -> None:
    """List local Kubernetes clusters (managed and detected)."""
    import ilum.cli.output as output_mod
    from ilum.cli.formatters import CommandResult, OutputFormat, ResultFormatter

    paths = IlumPaths.default()
    config_mgr = ConfigManager(paths)
    config = config_mgr.ensure_config()

    records = ClusterManager.list_local(config.clusters)

    if not records:
        console.info("No local clusters found. Create one with 'ilum cluster create'.")
        return

    fmt = OutputFormat(output_mod.console.output_format)

    if fmt != OutputFormat.TABLE:
        data_list = [
            {
                "name": r.name,
                "provider": r.provider,
                "context": r.kubecontext,
                "status": r.status,
                "source": r.source,
                "created_at": r.created_at[:19] if r.created_at else "",
            }
            for r in records
        ]
        result = CommandResult(data=data_list, summary=f"{len(data_list)} clusters")
        ResultFormatter().format(result, fmt, output_mod.console)
        return

    rows = []
    for r in records:
        status = r.status
        if status == "Running":
            status = "[green]Running[/green]"
        elif status == "Stopped":
            status = "[yellow]Stopped[/yellow]"

        source = r.source
        if source == "managed":
            source = "[green]managed[/green]"
        elif source == "detected":
            source = "[dim]detected[/dim]"

        rows.append(
            [
                r.name,
                r.provider,
                r.kubecontext,
                status,
                source,
                r.created_at[:19] if r.created_at else "",
            ]
        )
    console.table(
        "Local Clusters",
        ["Name", "Provider", "Context", "Status", "Source", "Created"],
        rows,
    )
