"""Contract tests: Secret CRUD.

These tests run identically on FakeK8sClient and the real K8s cluster,
proving the fake matches real K8s behavior for Secret operations.
"""

from __future__ import annotations

import pytest

from tests.backends.fake import FakeConflictError, FakeNotFoundError


class TestSecretCRUD:
    """Secret create / get / update / delete contract."""

    def test_create_and_get(self, k8s_client, tmp_namespace):
        body = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {"name": "test-secret"},
            "type": "Opaque",
            "stringData": {"password": "s3cret"},
        }
        created = k8s_client.create_secret(tmp_namespace, body)
        assert created["metadata"]["name"] == "test-secret"
        assert "resourceVersion" in created["metadata"]

        fetched = k8s_client.get_secret(tmp_namespace, "test-secret")
        assert fetched["metadata"]["name"] == "test-secret"
        # Verify data round-trips correctly (stringData→data decode)
        assert fetched["data"]["password"] == "s3cret"

    def test_create_already_exists(self, k8s_client, tmp_namespace):
        body = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {"name": "dup-secret"},
            "type": "Opaque",
            "stringData": {"key": "val"},
        }
        k8s_client.create_secret(tmp_namespace, body)
        with pytest.raises(FakeConflictError):
            k8s_client.create_secret(tmp_namespace, body)

    def test_delete_then_get_raises(self, k8s_client, tmp_namespace):
        body = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {"name": "del-secret"},
            "type": "Opaque",
            "stringData": {"a": "b"},
        }
        k8s_client.create_secret(tmp_namespace, body)
        k8s_client.delete_secret(tmp_namespace, "del-secret")
        with pytest.raises(FakeNotFoundError):
            k8s_client.get_secret(tmp_namespace, "del-secret")

    def test_update_changes_data(self, k8s_client, tmp_namespace):
        body = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {"name": "upd-secret"},
            "type": "Opaque",
            "stringData": {"key": "old"},
        }
        created = k8s_client.create_secret(tmp_namespace, body)
        rv = created["metadata"]["resourceVersion"]

        updated_body = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {"name": "upd-secret", "resourceVersion": rv},
            "type": "Opaque",
            "stringData": {"key": "new"},
        }
        updated = k8s_client.update_secret(tmp_namespace, "upd-secret", updated_body)
        assert updated["metadata"]["resourceVersion"] != rv

    def test_list_secrets_by_labels(self, k8s_client, tmp_namespace):
        body_a = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {
                "name": "labeled-a",
                "labels": {"team": "alpha"},
            },
            "type": "Opaque",
            "stringData": {"key": "a"},
        }
        body_b = {
            "apiVersion": "v1",
            "kind": "Secret",
            "metadata": {
                "name": "labeled-b",
                "labels": {"team": "beta"},
            },
            "type": "Opaque",
            "stringData": {"key": "b"},
        }
        k8s_client.create_secret(tmp_namespace, body_a)
        k8s_client.create_secret(tmp_namespace, body_b)

        alpha = k8s_client.list_secrets(tmp_namespace, labels={"team": "alpha"})
        alpha_names = {s["metadata"]["name"] for s in alpha}
        assert "labeled-a" in alpha_names
        assert "labeled-b" not in alpha_names

    def test_list_secrets_empty(self, k8s_client, tmp_namespace):
        result = k8s_client.list_secrets(tmp_namespace, labels={"nonexistent": "label"})
        assert result == []
