"""Tests for Phase 9 doctor checks (ingress, cert-manager, LB support)."""

from __future__ import annotations

import pytest

from kuberoku.factory import KuberokuFactory
from kuberoku.sdk.checks import CLUSTER_REQUIREMENTS
from tests.backends.fake import FakeK8sClient


@pytest.fixture()
def k8s() -> FakeK8sClient:
    return FakeK8sClient()


@pytest.fixture()
def factory(k8s: FakeK8sClient) -> KuberokuFactory:
    return KuberokuFactory(k8s_client=k8s, namespace="test-ns")


def _run_check(name: str, k8s: FakeK8sClient, factory: KuberokuFactory):  # type: ignore[no-untyped-def]
    for req in CLUSTER_REQUIREMENTS:
        if req.name == name:
            return req.check_fn(k8s, factory.namespace, factory.prefix, factory.domain)
    raise ValueError(f"Check '{name}' not found")


class TestIngressControllerCheck:
    def test_no_controller(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        result = _run_check("ingress_controller", k8s, factory)
        assert result.passed is False
        assert "No Ingress controller" in result.message

    def test_with_nginx(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.create_ingress_class(
            {
                "apiVersion": "networking.k8s.io/v1",
                "kind": "IngressClass",
                "metadata": {"name": "nginx"},
                "spec": {"controller": "k8s.io/ingress-nginx"},
            }
        )
        result = _run_check("ingress_controller", k8s, factory)
        assert result.passed is True
        assert "nginx" in result.message

    def test_with_k3s_traefik(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.inject_nodes(
            [
                {
                    "apiVersion": "v1",
                    "kind": "Node",
                    "metadata": {
                        "name": "k3s-node",
                        "labels": {"node.kubernetes.io/instance-type": "k3s"},
                    },
                }
            ]
        )
        result = _run_check("ingress_controller", k8s, factory)
        assert result.passed is True
        assert "traefik" in result.message


class TestIngressCrudCheck:
    def test_no_controller_skipped(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        result = _run_check("ingress_crud", k8s, factory)
        assert result.passed is True
        assert "skipped" in result.message

    def test_with_controller(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.create_ingress_class(
            {
                "apiVersion": "networking.k8s.io/v1",
                "kind": "IngressClass",
                "metadata": {"name": "nginx"},
                "spec": {"controller": "k8s.io/ingress-nginx"},
            }
        )
        result = _run_check("ingress_crud", k8s, factory)
        assert result.passed is True
        assert "works" in result.message


class TestCertManagerCheck:
    def test_not_installed(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        result = _run_check("cert_manager", k8s, factory)
        assert result.passed is False
        assert "not detected" in result.message

    def test_installed(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.create_deployment(
            "cert-manager",
            {
                "apiVersion": "apps/v1",
                "kind": "Deployment",
                "metadata": {"name": "cert-manager"},
                "spec": {
                    "replicas": 1,
                    "selector": {"matchLabels": {"app": "cert-manager"}},
                    "template": {
                        "metadata": {"labels": {"app": "cert-manager"}},
                        "spec": {"containers": [{"name": "cm", "image": "cert-manager:v1.14"}]},
                    },
                },
            },
        )
        result = _run_check("cert_manager", k8s, factory)
        assert result.passed is True
        assert "installed" in result.message


class TestLbSupportCheck:
    def test_default_cloud(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        result = _run_check("lb_support", k8s, factory)
        assert result.passed is True
        assert "cloud" in result.message

    def test_k3s(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.inject_nodes(
            [
                {
                    "apiVersion": "v1",
                    "kind": "Node",
                    "metadata": {
                        "name": "k3s-node",
                        "labels": {"node.kubernetes.io/instance-type": "k3s"},
                    },
                }
            ]
        )
        result = _run_check("lb_support", k8s, factory)
        assert result.passed is True
        assert "k3s" in result.message

    def test_kind_without_metallb(self, k8s: FakeK8sClient, factory: KuberokuFactory) -> None:
        k8s.inject_nodes(
            [
                {
                    "apiVersion": "v1",
                    "kind": "Node",
                    "metadata": {"name": "kind-control-plane"},
                }
            ]
        )
        result = _run_check("lb_support", k8s, factory)
        assert result.passed is False
        assert "kind" in result.message


class TestCheckRegistryHas14Checks:
    def test_total_checks(self) -> None:
        assert len(CLUSTER_REQUIREMENTS) == 14
