"""E2E: CRD installation, policy CRUD, and status subresource."""

import pytest
from kubernetes.client.exceptions import ApiException

CRD_GROUP = "citadel.dev"
CRD_VERSION = "v1alpha1"
CRD_PLURAL = "nodeterminationpolicies"

pytestmark = pytest.mark.usefixtures("cluster_reachable", "install_crds")


class TestCRDInstallation:
    """Verify the CRD is installed and established."""

    def test_crd_is_established(self, k8s_clients):
        ext = k8s_clients["extensions"]
        crd = ext.read_custom_resource_definition(f"{CRD_PLURAL}.{CRD_GROUP}")

        established = False
        for cond in crd.status.conditions or []:
            if cond.type == "Established" and cond.status == "True":
                established = True
                break
        assert established, "CRD is not in Established state"


class TestPolicyCRUD:
    """Create, read, update, and delete NodeTerminationPolicy resources."""

    def test_create_age_policy(self, k8s_clients, create_policy):
        custom = k8s_clients["custom"]
        result = create_policy(
            name="e2e-age-test",
            spec={
                "reason": "E2E test: node too old",
                "priority": 10,
                "selector": {"maxAgeHours": 48},
            },
        )

        assert result["metadata"]["name"] == "e2e-age-test"
        assert result["spec"]["reason"] == "E2E test: node too old"
        assert result["spec"]["selector"]["maxAgeHours"] == 48

        # Read it back
        fetched = custom.get_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-age-test",
        )
        assert fetched["spec"]["priority"] == 10

    def test_create_health_policy(self, create_policy):
        result = create_policy(
            name="e2e-health-test",
            spec={
                "reason": "E2E test: disk pressure",
                "priority": 100,
                "selector": {
                    "conditions": [{"type": "DiskPressure", "status": "True"}],
                },
            },
        )

        assert result["spec"]["selector"]["conditions"][0]["type"] == "DiskPressure"
        assert result["spec"]["selector"]["conditions"][0]["status"] == "True"

    def test_update_policy_priority(self, k8s_clients, create_policy):
        custom = k8s_clients["custom"]
        create_policy(
            name="e2e-update-test",
            spec={
                "reason": "E2E test: update priority",
                "priority": 10,
                "selector": {"maxAgeHours": 72},
            },
        )

        # Update priority
        custom.patch_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-update-test",
            body={"spec": {"priority": 50}},
        )

        fetched = custom.get_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-update-test",
        )
        assert fetched["spec"]["priority"] == 50

    def test_delete_policy(self, k8s_clients, create_policy):
        custom = k8s_clients["custom"]
        create_policy(
            name="e2e-delete-test",
            spec={
                "reason": "E2E test: delete me",
                "selector": {"maxAgeHours": 24},
            },
        )

        custom.delete_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-delete-test",
        )

        with pytest.raises(ApiException) as exc_info:
            custom.get_cluster_custom_object(
                group=CRD_GROUP,
                version=CRD_VERSION,
                plural=CRD_PLURAL,
                name="e2e-delete-test",
            )
        assert exc_info.value.status == 404


class TestPolicyStatus:
    """Status subresource updates."""

    def test_update_status_subresource(self, k8s_clients, create_policy):
        custom = k8s_clients["custom"]
        create_policy(
            name="e2e-status-test",
            spec={
                "reason": "E2E test: status update",
                "selector": {"maxAgeHours": 24},
            },
        )

        # Patch status subresource
        custom.patch_cluster_custom_object_status(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-status-test",
            body={
                "status": {
                    "lastEvaluated": "2025-01-01T00:00:00Z",
                    "nodesMatched": 3,
                    "nodesTerminated": 1,
                }
            },
        )

        fetched = custom.get_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-status-test",
        )
        status = fetched.get("status", {})
        assert status["nodesMatched"] == 3
        assert status["nodesTerminated"] == 1
        assert "lastEvaluated" in status

    def test_status_does_not_affect_spec(self, k8s_clients, create_policy):
        custom = k8s_clients["custom"]
        create_policy(
            name="e2e-status-spec-test",
            spec={
                "reason": "E2E test: status vs spec",
                "priority": 42,
                "selector": {"maxAgeHours": 48},
            },
        )

        # Patch status
        custom.patch_cluster_custom_object_status(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-status-spec-test",
            body={"status": {"nodesMatched": 10}},
        )

        # Verify spec is unchanged
        fetched = custom.get_cluster_custom_object(
            group=CRD_GROUP,
            version=CRD_VERSION,
            plural=CRD_PLURAL,
            name="e2e-status-spec-test",
        )
        assert fetched["spec"]["priority"] == 42
        assert fetched["spec"]["reason"] == "E2E test: status vs spec"
