"""Ingress controller, cert-manager, and LB support detection.

Shared infrastructure used by DomainsService, GatewayService, and Doctor checks.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from kuberoku.models import IngressControllerInfo

if TYPE_CHECKING:
    from kuberoku.k8s.protocols import K8sClientProtocol


def _is_k3s(k8s: K8sClientProtocol) -> bool:
    """Detect k3s by checking node labels."""
    try:
        nodes = k8s.list_nodes()
        for node in nodes:
            node_labels = node.get("metadata", {}).get("labels", {})
            if node_labels.get("node.kubernetes.io/instance-type") == "k3s":
                return True
    except Exception:
        pass
    return False


def _is_docker_desktop(k8s: K8sClientProtocol) -> bool:
    """Detect Docker Desktop by node name."""
    try:
        nodes = k8s.list_nodes()
        for node in nodes:
            name = node.get("metadata", {}).get("name", "")
            if name == "docker-desktop":
                return True
    except Exception:
        pass
    return False


def _is_kind(k8s: K8sClientProtocol) -> bool:
    """Detect kind by node name pattern."""
    try:
        nodes = k8s.list_nodes()
        for node in nodes:
            name = node.get("metadata", {}).get("name", "")
            if "kind-" in name:
                return True
    except Exception:
        pass
    return False


def _is_minikube(k8s: K8sClientProtocol) -> bool:
    """Detect minikube by node label."""
    try:
        nodes = k8s.list_nodes()
        for node in nodes:
            node_labels = node.get("metadata", {}).get("labels", {})
            if "minikube.k8s.io/name" in node_labels:
                return True
    except Exception:
        pass
    return False


def detect_ingress_controller(
    k8s: K8sClientProtocol,
    namespace: str,
) -> IngressControllerInfo | None:
    """Detect the installed Ingress controller.

    Detection order:
    1. IngressClass resources (canonical K8s way)
    2. Known namespaces (ingress-nginx, traefik, kube-system)
    3. k3s built-in traefik
    """
    # 1. Check IngressClass resources
    try:
        classes = k8s.list_ingress_classes()
        if classes:
            ic = classes[0]
            ic_name = ic.get("metadata", {}).get("name", "")
            controller = ic.get("spec", {}).get("controller", "")
            is_nginx = "nginx" in controller.lower()
            return IngressControllerInfo(
                name="nginx" if is_nginx else ic_name,
                class_name=ic_name,
                namespace="ingress-nginx" if is_nginx else "kube-system",
                supports_tcp_proxy=is_nginx,
            )
    except Exception:
        pass

    # 2. k3s has built-in traefik
    if _is_k3s(k8s):
        return IngressControllerInfo(
            name="traefik",
            class_name="traefik",
            namespace="kube-system",
            supports_tcp_proxy=False,
        )

    # 3. Check known namespaces for deployments
    for check_ns, name, cls, tcp in [
        ("ingress-nginx", "nginx", "nginx", True),
        ("traefik", "traefik", "traefik", False),
    ]:
        try:
            deps = k8s.list_deployments(check_ns)
            if deps:
                return IngressControllerInfo(
                    name=name,
                    class_name=cls,
                    namespace=check_ns,
                    supports_tcp_proxy=tcp,
                )
        except Exception:
            continue

    return None


def detect_cert_manager(k8s: K8sClientProtocol) -> bool:
    """Check if cert-manager is installed.

    Looks for deployments in the cert-manager namespace.
    """
    try:
        deps = k8s.list_deployments("cert-manager")
        return len(deps) > 0
    except Exception:
        return False


def detect_lb_support(k8s: K8sClientProtocol) -> tuple[bool, str]:
    """Detect LoadBalancer support.

    Returns (supported, description).
    """
    # k3s has ServiceLB built-in
    if _is_k3s(k8s):
        return True, "k3s ServiceLB"

    # Docker Desktop has built-in LB support
    if _is_docker_desktop(k8s):
        return True, "Docker Desktop"

    # minikube with tunnel
    if _is_minikube(k8s):
        return True, "minikube (requires 'minikube tunnel')"

    # Check for MetalLB
    try:
        deps = k8s.list_deployments("metallb-system")
        if deps:
            return True, "MetalLB"
    except Exception:
        pass

    # kind without MetalLB — no LB support
    if _is_kind(k8s):
        return False, "kind (install MetalLB for LoadBalancer support)"

    # Cloud or unknown — assume cloud provider handles it
    return True, "cloud provider"
