from __future__ import annotations

from copy import deepcopy

from src.models.drift import DriftLevel
from src.services.drift_detector import DriftDetector, GitStateReader


def test_git_state_reader_applies_kustomize_labels_and_images(tmp_path):
    prod_dir = tmp_path / "k8s" / "awoooi-prod"
    prod_dir.mkdir(parents=True)
    (prod_dir / "kustomization.yaml").write_text(
        """
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: awoooi-prod
commonLabels:
  environment: prod
  system: awoooi
resources:
  - deployment.yaml
images:
  - name: registry.local/library/api:IMAGE_TAG_PLACEHOLDER
    newName: registry.local/awoooi/api
    newTag: abc123
""",
        encoding="utf-8",
    )
    (prod_dir / "deployment.yaml").write_text(
        """
apiVersion: apps/v1
kind: Deployment
metadata:
  name: awoooi-api
spec:
  selector:
    matchLabels:
      app: awoooi-api
  template:
    metadata:
      labels:
        app: awoooi-api
    spec:
      containers:
        - name: api
          image: registry.local/library/api:IMAGE_TAG_PLACEHOLDER
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: awoooi-api
                topologyKey: kubernetes.io/hostname
---
apiVersion: v1
kind: Service
metadata:
  name: awoooi-api-svc
spec:
  selector:
    app: awoooi-api
  ports:
    - port: 8000
      targetPort: 8000
""",
        encoding="utf-8",
    )

    state = GitStateReader(str(tmp_path / "k8s"))._read_sync("awoooi-prod")

    deployment = state["Deployment/awoooi-api"]
    template = deployment["spec"]["template"]
    assert deployment["metadata"]["namespace"] == "awoooi-prod"
    assert deployment["spec"]["selector"]["matchLabels"]["environment"] == "prod"
    assert template["metadata"]["labels"]["system"] == "awoooi"
    assert (
        template["spec"]["containers"][0]["image"]
        == "registry.local/awoooi/api:abc123"
    )
    affinity_selector = template["spec"]["affinity"]["podAntiAffinity"][
        "preferredDuringSchedulingIgnoredDuringExecution"
    ][0]["podAffinityTerm"]["labelSelector"]["matchLabels"]
    assert affinity_selector["environment"] == "prod"
    assert affinity_selector["system"] == "awoooi"

    service = state["Service/awoooi-api-svc"]
    assert service["metadata"]["namespace"] == "awoooi-prod"
    assert service["spec"]["selector"]["environment"] == "prod"
    assert service["spec"]["selector"]["system"] == "awoooi"


def test_git_state_reader_prefers_gitea_main_raw_files(monkeypatch):
    reader = GitStateReader("k8s")
    remote_files = {
        "k8s/awoooi-prod/kustomization.yaml": """
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: awoooi-prod
commonLabels:
  environment: prod
  system: awoooi
resources:
  - deployment.yaml
images:
  - name: registry.local/library/api:IMAGE_TAG_PLACEHOLDER
    newName: registry.local/awoooi/api
    newTag: live-main-sha
""",
        "k8s/awoooi-prod/deployment.yaml": """
apiVersion: apps/v1
kind: Deployment
metadata:
  name: awoooi-api
spec:
  selector:
    matchLabels:
      app: awoooi-api
  template:
    metadata:
      labels:
        app: awoooi-api
    spec:
      containers:
        - name: api
          image: registry.local/library/api:IMAGE_TAG_PLACEHOLDER
""",
    }

    def fake_fetch(settings, path):
        return remote_files.get(path)

    monkeypatch.setattr(reader, "_fetch_gitea_raw", fake_fetch)

    state = reader._read_sync("awoooi-prod")

    assert set(state) == {"Deployment/awoooi-api"}
    container = state["Deployment/awoooi-api"]["spec"]["template"]["spec"]["containers"][0]
    assert container["image"] == "registry.local/awoooi/api:live-main-sha"
    assert state["Deployment/awoooi-api"]["spec"]["selector"]["matchLabels"]["system"] == "awoooi"


def test_kubernetes_api_defaults_do_not_create_drift():
    detector = DriftDetector()
    git_res = {
        "kind": "Deployment",
        "spec": {
            "selector": {"matchLabels": {"app": "awoooi-api"}},
            "template": {
                "metadata": {"labels": {"app": "awoooi-api"}},
                "spec": {
                    "serviceAccountName": "awoooi-executor",
                    "containers": [
                        {
                            "name": "api",
                            "image": "registry.local/awoooi/api:abc123",
                            "ports": [{"containerPort": 8000, "name": "http"}],
                            "readinessProbe": {
                                "httpGet": {"path": "/api/v1/health", "port": 8000},
                                "periodSeconds": 5,
                            },
                            "env": [
                                {
                                    "name": "POD_NAME",
                                    "valueFrom": {
                                        "fieldRef": {"fieldPath": "metadata.name"}
                                    },
                                }
                            ],
                        }
                    ],
                    "volumes": [
                        {"name": "runtime-secret", "secret": {"secretName": "s"}},
                        {"name": "runtime-config", "configMap": {"name": "c"}},
                    ],
                },
            },
        },
    }
    actual_res = deepcopy(git_res)
    pod_spec = actual_res["spec"]["template"]["spec"]
    pod_spec.update(
        {
            "serviceAccount": "awoooi-executor",
            "restartPolicy": "Always",
            "dnsPolicy": "ClusterFirst",
            "schedulerName": "default-scheduler",
            "terminationGracePeriodSeconds": 30,
            "securityContext": {},
        }
    )
    container = pod_spec["containers"][0]
    container["terminationMessagePath"] = "/dev/termination-log"
    container["terminationMessagePolicy"] = "File"
    container["ports"][0]["protocol"] = "TCP"
    container["readinessProbe"]["successThreshold"] = 1
    container["readinessProbe"]["httpGet"]["scheme"] = "HTTP"
    container["env"][0]["valueFrom"]["fieldRef"]["apiVersion"] = "v1"
    pod_spec["volumes"][0]["secret"]["defaultMode"] = 420
    pod_spec["volumes"][1]["configMap"]["defaultMode"] = 420
    actual_res["spec"]["template"]["metadata"]["annotations"] = {
        "kubectl.kubernetes.io/restartedAt": "2026-05-19T00:00:00+08:00"
    }

    assert (
        detector._diff_resources(
            git_res,
            actual_res,
            "Deployment",
            "awoooi-api",
            "awoooi-prod",
        )
        == []
    )


def test_service_runtime_defaults_do_not_create_drift():
    detector = DriftDetector()
    git_res = {
        "kind": "Service",
        "spec": {
            "type": "NodePort",
            "selector": {"app": "awoooi-api"},
            "ports": [{"port": 8000, "targetPort": 8000, "nodePort": 32334}],
        },
    }
    actual_res = deepcopy(git_res)
    actual_res["spec"].update(
        {
            "clusterIP": "10.43.156.119",
            "clusterIPs": ["10.43.156.119"],
            "ipFamilies": ["IPv4"],
            "ipFamilyPolicy": "SingleStack",
            "internalTrafficPolicy": "Cluster",
            "externalTrafficPolicy": "Cluster",
            "sessionAffinity": "None",
        }
    )
    actual_res["spec"]["ports"][0]["protocol"] = "TCP"

    assert (
        detector._diff_resources(
            git_res,
            actual_res,
            "Service",
            "awoooi-api-svc",
            "awoooi-prod",
        )
        == []
    )


def test_real_container_env_drift_remains_visible():
    detector = DriftDetector()
    git_res = {
        "kind": "Deployment",
        "spec": {
            "template": {
                "metadata": {"labels": {"app": "awoooi-api"}},
                "spec": {
                    "containers": [
                        {
                            "name": "api",
                            "image": "registry.local/awoooi/api:abc123",
                            "env": [{"name": "USE_AI_ROUTER", "value": "true"}],
                        }
                    ]
                },
            }
        },
    }
    actual_res = deepcopy(git_res)
    actual_res["spec"]["template"]["spec"]["containers"][0]["env"].append(
        {"name": "DUMMY_DEPLOY", "value": "1777914462"}
    )

    items = detector._diff_resources(
        git_res,
        actual_res,
        "Deployment",
        "awoooi-api",
        "awoooi-prod",
    )

    assert [item.field_path for item in items] == ["spec.template.spec.containers"]
    assert items[0].drift_level == DriftLevel.MEDIUM
