"""``ilum cleanup`` command — full environment teardown."""

from __future__ import annotations

import typer

import ilum.cli.output as output_mod
from ilum.cli.defaults import resolve_profile_defaults
from ilum.config.manager import ConfigManager
from ilum.config.paths import IlumPaths
from ilum.core.cleanup import (
    count_files_in_dir,
    detect_dependencies,
    docker_has_running_containers,
    remove_cli_directories,
    remove_dependency,
    remove_helm_repo,
    uninstall_cli,
)
from ilum.core.helm import HelmClient
from ilum.core.kubernetes import KubeClient
from ilum.core.modules import ModuleResolver
from ilum.core.release import ReleaseManager, ReleasePlan
from ilum.errors import IlumError
from ilum.wizard.cluster import ClusterManager, ClusterProvider

_PROTECTED_NAMESPACES = frozenset({"default", "kube-system", "kube-public", "kube-node-lease"})


def cleanup(
    cluster: bool = typer.Option(False, "--cluster", help="Also delete local k8s cluster."),
    config: bool = typer.Option(False, "--config", help="Also remove CLI config/state/cache."),
    deps: bool = typer.Option(
        False, "--deps", help="Also remove dependencies (helm, kubectl, etc.)."
    ),
    self_uninstall: bool = typer.Option(
        False, "--self", help="Also uninstall the CLI itself (always last)."
    ),
    all_tiers: bool = typer.Option(
        False, "--all", help="Enable --cluster --config --deps (not --self)."
    ),
    release: str | None = typer.Option(
        None, "--release", "-r", show_default="from profile", help="Helm release name."
    ),
    namespace: str | None = typer.Option(
        None, "--namespace", "-n", show_default="from profile", help="Kubernetes namespace."
    ),
    context: str | None = typer.Option(
        None, "--context", show_default="from profile", help="Kubernetes context."
    ),
    yes: bool = typer.Option(False, "--yes", "-y", help="Skip all confirmations."),
    dry_run: bool = typer.Option(False, "--dry-run", help="Preview without executing."),
) -> None:
    """Full environment teardown with tiered, opt-in destructiveness."""
    if all_tiers:
        cluster = True
        config = True
        deps = True

    release, namespace, context = resolve_profile_defaults(release, namespace, context)
    console = output_mod.console
    paths = IlumPaths.default()

    # ── Tier 1: Uninstall Helm release + PVCs + namespace ──────────
    _tier_uninstall(release, namespace, context, yes, dry_run, console, paths)

    # ── Tier 2: Delete local cluster ───────────────────────────────
    if cluster:
        _tier_cluster(yes, dry_run, console, paths)

    # ── Tier 3: Remove CLI directories + Helm repo ─────────────────
    if config:
        _tier_config(yes, dry_run, console, paths)

    # ── Tier 4: Remove dependencies ────────────────────────────────
    if deps:
        _tier_deps(yes, dry_run, console)

    # ── Tier 5: Uninstall CLI itself ───────────────────────────────
    if self_uninstall:
        _tier_self(yes, dry_run, console)

    if not dry_run:
        console.success("Cleanup complete.")


def _tier_uninstall(
    release: str,
    namespace: str,
    context: str,
    yes: bool,
    dry_run: bool,
    console: output_mod.IlumConsole,
    paths: IlumPaths,
) -> None:
    """Tier 1: Uninstall Helm release, delete PVCs and namespace."""
    console.info("[bold]Tier 1 — Ilum Release[/bold]")

    try:
        paths.ensure_dirs()
        mgr = ReleaseManager(
            helm=HelmClient(kubecontext=context, namespace=namespace),
            k8s=KubeClient(kubecontext=context),
            resolver=ModuleResolver(),
            config_mgr=ConfigManager(paths),
            paths=paths,
        )

        if not mgr.release_exists(release):
            console.info(f"  Release '{release}' not found — skipping.")
            return

        # Preview
        plan = ReleasePlan(action="uninstall", release=release, namespace=namespace, chart="")

        pvc_count = 0
        try:
            pvcs = mgr.k8s.list_pvcs(namespace)
            pvc_count = len(pvcs)
        except Exception:  # noqa: BLE001
            pass

        if dry_run:
            console.info(f'  Would uninstall release "{release}" from namespace "{namespace}"')
            console.info(f"  Would delete {pvc_count} PersistentVolumeClaim(s)")
            if namespace in _PROTECTED_NAMESPACES:
                console.info(f'  Would skip deletion of protected namespace "{namespace}"')
            else:
                console.info(f'  Would delete namespace "{namespace}"')
            return

        # Confirmation
        if not yes:
            console.warning(
                f'Release "{release}", {pvc_count} PVC(s), '
                f'and namespace "{namespace}" will be deleted.'
            )
            typed = console.prompt_text(
                f"  Type the release name [bold]{release}[/bold] to confirm"
            )
            if typed != release:
                console.error("Release name does not match. Tier 1 aborted.")
                return

        # Execute
        with console.status_spinner("Uninstalling Ilum..."):
            mgr.execute(plan)
        console.success(f"Release '{release}' uninstalled.")

        with console.status_spinner("Deleting PersistentVolumeClaims..."):
            deleted = mgr.k8s.delete_pvcs(namespace)
        if deleted:
            console.success(f"Deleted {len(deleted)} PVC(s).")

        if namespace in _PROTECTED_NAMESPACES:
            console.info(f"Skipping deletion of protected namespace '{namespace}'.")
        else:
            with console.status_spinner(f"Deleting namespace '{namespace}'..."):
                mgr.k8s.delete_namespace(namespace)
            console.success(f"Namespace '{namespace}' deleted.")

        mgr.save_enabled_modules([], release=release)

    except IlumError as exc:
        console.handle_error(exc)
        console.warning("Tier 1 failed — continuing with remaining tiers.")


def _tier_cluster(
    yes: bool,
    dry_run: bool,
    console: output_mod.IlumConsole,
    paths: IlumPaths,
) -> None:
    """Tier 2: Delete CLI-managed local cluster."""
    console.info("[bold]Tier 2 — Local Cluster[/bold]")

    try:
        config_mgr = ConfigManager(paths)
        cfg = config_mgr.ensure_config()

        managed = [r for r in cfg.clusters if r.source == "managed"]
        if not managed:
            console.info("  No CLI-managed clusters found — skipping.")
            return

        for record in managed:
            if dry_run:
                console.info(f'  Would delete cluster "{record.name}" ({record.provider})')
                continue

            if not yes:
                typed = console.prompt_text(
                    f"  Type cluster name [bold]{record.name}[/bold] to confirm deletion"
                )
                if typed != record.name:
                    console.info(f"  Skipping cluster '{record.name}'.")
                    continue

            try:
                prov = ClusterProvider(record.provider)
                mgr = ClusterManager()
                mgr.delete(prov, record.name, console)
            except Exception as exc:  # noqa: BLE001
                console.warning(f"Failed to delete cluster '{record.name}': {exc}")

        if not dry_run:
            cfg.clusters = [r for r in cfg.clusters if r.source != "managed"]
            config_mgr.save(cfg)

    except IlumError as exc:
        console.handle_error(exc)
        console.warning("Tier 2 failed — continuing with remaining tiers.")


def _tier_config(
    yes: bool,
    dry_run: bool,
    console: output_mod.IlumConsole,
    paths: IlumPaths,
) -> None:
    """Tier 3: Remove CLI directories and Helm repo."""
    console.info("[bold]Tier 3 — CLI Configuration[/bold]")

    dirs = paths.all_dirs()

    for d in dirs:
        if d.exists():
            count = count_files_in_dir(d)
            console.info(f"  {d} (exists, {count} item(s))")
        else:
            console.info(f"  {d} (does not exist)")

    if dry_run:
        console.info("  Would remove the above directories.")
        if remove_helm_repo(dry_run=True):
            console.info("  Would remove Helm repo 'ilum'.")
        return

    if not yes:
        typed = console.prompt_text("  Type [bold]DELETE[/bold] to confirm removal")
        if typed != "DELETE":
            console.info("  Tier 3 aborted.")
            return

    removed = remove_cli_directories(dirs)
    for d in removed:
        console.success(f"Removed {d}")

    if remove_helm_repo():
        console.success("Removed Helm repo 'ilum'.")


def _tier_deps(
    yes: bool,
    dry_run: bool,
    console: output_mod.IlumConsole,
) -> None:
    """Tier 4: Remove dependencies."""
    console.info("[bold]Tier 4 — Dependencies[/bold]")

    detected = detect_dependencies()
    if not detected:
        console.info("  No dependencies found to remove.")
        return

    for dep in detected:
        version_info = f" ({dep.version})" if dep.version else ""
        method_info = ""
        if dep.name in ("minikube", "k3d", "kind"):
            method_info = " — will delete all clusters first"
        if dep.name == "docker":
            method_info = f" — via {dep.removal_method}"

        if dry_run:
            console.info(f"  Would remove: {dep.name} ({dep.path}){version_info}{method_info}")
            continue

        # Docker gets extra-strong confirmation
        if dep.name == "docker":
            if docker_has_running_containers():
                console.warning(
                    "Docker has running containers! "
                    "All containers, images, and volumes will be lost."
                )
            confirm_text = "REMOVE DOCKER"
        else:
            confirm_text = "REMOVE"

        if not yes:
            typed = console.prompt_text(
                f"  Type [bold]{confirm_text}[/bold] to remove "
                f"{dep.name} ({dep.path}){version_info}"
            )
            if typed != confirm_text:
                console.info(f"  Skipping {dep.name}.")
                continue

        if remove_dependency(dep):
            console.success(f"Removed {dep.name}.")
        else:
            console.warning(f"Failed to remove {dep.name}.")

    # Note about Docker
    if not any(d.name == "docker" for d in detected):
        console.info("  Docker was not found.")


def _tier_self(
    yes: bool,
    dry_run: bool,
    console: output_mod.IlumConsole,
) -> None:
    """Tier 5: Uninstall the CLI itself."""
    console.info("[bold]Tier 5 — CLI Self-Uninstall[/bold]")

    if dry_run:
        console.info("  Would uninstall the ilum CLI package.")
        return

    if not yes:
        typed = console.prompt_text("  Type [bold]UNINSTALL[/bold] to remove the ilum CLI")
        if typed != "UNINSTALL":
            console.info("  Tier 5 aborted.")
            return

    success, hint = uninstall_cli()
    if success:
        console.success("CLI uninstalled. Goodbye.")
    else:
        console.warning(f"Could not uninstall the CLI automatically. {hint}")
