"""``ilum quickstart`` command — one-command install with sensible defaults."""

from __future__ import annotations

import typer

import ilum.cli.output as output_mod
from ilum.config.manager import ConfigManager
from ilum.config.models import ClusterConfig, ProfileConfig
from ilum.config.paths import IlumPaths
from ilum.constants import (
    DEFAULT_CHART_REF,
    DEFAULT_NAMESPACE,
    DEFAULT_RELEASE_NAME,
    is_local_chart,
)
from ilum.core.helm import HelmClient
from ilum.core.kubernetes import KubeClient
from ilum.core.modules import ModuleResolver
from ilum.core.release import ReleaseManager
from ilum.errors import IlumError
from ilum.wizard.cluster import PRESETS, ClusterManager, ClusterProvider
from ilum.wizard.deps import ToolInstaller


def _build_manager(
    context: str,
    namespace: str,
    timeout: str,
) -> ReleaseManager:
    paths = IlumPaths.default()
    paths.ensure_dirs()
    return ReleaseManager(
        helm=HelmClient(kubecontext=context, namespace=namespace, timeout=timeout),
        k8s=KubeClient(kubecontext=context),
        resolver=ModuleResolver(),
        config_mgr=ConfigManager(paths),
        paths=paths,
    )


def _cluster_reachable() -> str:
    """Return the current kubecontext if the cluster is reachable, else ''."""
    try:
        from kubernetes import client as k8s_client
        from kubernetes import config as k8s_config

        k8s_config.load_kube_config()
        _, current = k8s_config.list_kube_config_contexts()
        if not current:
            return ""
        context_name = current["name"]
        # Quick connectivity check
        api = k8s_client.CoreV1Api()
        api.list_namespace(_request_timeout=5)
        return context_name
    except Exception:  # noqa: BLE001
        return ""


def quickstart(
    provider: str = typer.Option(
        "minikube",
        "--provider",
        help="Local cluster provider if a new cluster is needed (minikube, k3d, kind).",
    ),
    profile: str = typer.Option(
        "default",
        "--profile",
        "-p",
        help="Profile name to create.",
    ),
    module: list[str] | None = typer.Option(  # noqa: B008
        None,
        "--module",
        "-m",
        help="Additional module to enable (repeatable).",
    ),
    preset: str = typer.Option(
        "",
        "--preset",
        help="Deployment preset (development, production, data-engineering, air-gapped).",
    ),
    chart: str = typer.Option(
        "", "--chart", help="Chart reference or local path (default: ilum/ilum)."
    ),
    devel: bool = typer.Option(False, "--devel", help="Include pre-release chart versions."),
    timeout: str = typer.Option("15m", "--timeout", help="Helm install timeout."),
) -> None:
    """Install Ilum in one command with sensible defaults.

    Detects an existing Kubernetes cluster or creates a local one,
    then installs Ilum with all default modules enabled.
    """
    console = output_mod.console

    console.panel(
        "[bold]Ilum Quickstart[/bold]\n\n"
        "One-command setup: preflight checks, cluster detection, and install.",
        title="ilum quickstart",
    )

    try:
        # Step 1: Preflight checks
        console.info("Step 1/4: Checking prerequisites...")
        installer = ToolInstaller()
        results = installer.check_and_install(console, non_interactive=False)
        from ilum.doctor.checks import CheckStatus

        failures = [r for r in results if r.status == CheckStatus.FAIL]
        if failures:
            console.warning(
                f"{len(failures)} tool(s) missing or outdated. Some features may not work."
            )
        else:
            console.success("All prerequisites met.")

        # Step 2: Cluster detection / creation
        console.info("Step 2/4: Detecting Kubernetes cluster...")
        kubecontext = _cluster_reachable()

        if kubecontext:
            console.success(f"Cluster reachable (context: {kubecontext})")
        else:
            console.info("No reachable cluster found. Creating a local cluster...")
            cluster_provider = ClusterProvider(provider)
            cluster_preset = PRESETS["dev"]
            cluster_mgr = ClusterManager()

            try:
                record = cluster_mgr.create(cluster_provider, cluster_preset, console)
                kubecontext = record.kubecontext

                # Save cluster record to config
                paths = IlumPaths.default()
                paths.ensure_dirs()
                config_mgr = ConfigManager(paths)
                config = config_mgr.ensure_config()
                config.clusters.append(record)
                config_mgr.save(config)
            except IlumError as exc:
                console.handle_error(exc)
                console.info("After resolving the issue, re-run 'ilum quickstart'.")
                raise typer.Exit(code=1) from exc
            except Exception as exc:
                console.error(f"Cluster creation failed: {exc}")
                console.info("Please create a cluster manually and re-run 'ilum quickstart'.")
                raise typer.Exit(code=1) from exc

        # Step 3: Initialize profile
        console.info("Step 3/4: Configuring profile...")
        namespace = DEFAULT_NAMESPACE
        release = DEFAULT_RELEASE_NAME

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

        from ilum.core.presets import get_preset

        resolver = ModuleResolver()
        preset_obj = None
        preset_set_flags: list[str] = []
        if preset:
            preset_obj = get_preset(preset)
            if preset_obj is None:
                console.error(f"Unknown preset: '{preset}'")
                raise typer.Exit(code=1)

        if preset_obj:
            modules = list(preset_obj.modules)
            # Collect preset set_flags, filtering out placeholder values
            preset_set_flags = [
                f
                for f in preset_obj.set_flags
                if not any(
                    f.endswith(f"=<{ri.split('.')[-1].upper()}>")
                    for ri in preset_obj.requires_input
                )
                and not f.endswith("=<REGISTRY>")
            ]
        else:
            modules = resolver.default_enabled()

        # Add any extra modules the user requested
        if module:
            extra = [m for m in module if m not in modules]
            modules.extend(extra)

        # Always resolve dependencies
        modules, dep_msgs = resolver.resolve_selection(modules)
        for msg in dep_msgs:
            console.info(msg)

        config.profiles[profile] = ProfileConfig(
            name=profile,
            release_name=release,
            cluster=ClusterConfig(
                kubecontext=kubecontext,
                namespace=namespace,
            ),
            enabled_modules=sorted(modules),
        )
        config.active_profile = profile
        config_mgr.save(config)
        console.success(f"Profile '{profile}' configured with {len(modules)} modules.")

        # Step 4: Install
        console.info("Step 4/4: Installing Ilum...")
        mgr = _build_manager(kubecontext, namespace, timeout)
        chart_ref = chart or DEFAULT_CHART_REF
        if not is_local_chart(chart_ref):
            mgr.ensure_repo()

        plan = mgr.plan_install(
            release=release,
            chart=chart_ref,
            modules=modules,
            values_files=None,
            set_flags=preset_set_flags or None,
            version="",
            atomic=False,
            devel=devel,
        )

        if plan.warnings:
            for w in plan.warnings:
                console.warning(w)

        console.command_preview(mgr.preview_command(plan))

        # Ensure namespace exists
        try:
            if not mgr.k8s.namespace_exists(namespace):
                console.info(f"Namespace '{namespace}' does not exist — creating it.")
                mgr.k8s.create_namespace(namespace)
                console.success(f"Namespace '{namespace}' created.")
        except IlumError as ns_exc:
            console.handle_error(ns_exc)
            raise typer.Exit(code=1) from ns_exc

        # NodePort conflict resolution (auto-assign in non-interactive mode)
        from ilum.cli.install_cmd import _resolve_nodeport_conflicts

        try:
            _resolve_nodeport_conflicts(mgr, plan, console, yes=True)
        except IlumError as np_exc:
            console.handle_error(np_exc)
            raise typer.Exit(code=1) from np_exc

        from ilum.cli.progress import execute_with_progress

        execute_with_progress(mgr, plan, console, message="Installing Ilum...")

        # Save release to profile
        config = mgr.config_mgr.load()
        if profile in config.profiles:
            config.profiles[profile].release_name = release
            config.profiles[profile].cluster.namespace = namespace
            mgr.config_mgr.save(config)

        mgr.save_enabled_modules(sorted(modules), release=release)

        console.success("Ilum installed successfully!")
        console.info("")
        console.info("Next steps:")
        console.info("  ilum status          Show release and pod status")
        console.info("  ilum module enable   Enable additional modules")
        console.info("  ilum logs core       View Ilum Core logs")
        console.info("  ilum upgrade         Upgrade to a newer version")

    except IlumError as exc:
        console.handle_error(exc)
        raise typer.Exit(code=1) from exc
    except KeyboardInterrupt:
        console.warning("Quickstart interrupted.")
        raise typer.Exit(code=130) from None
