"""Shared fixtures for domain tests.

Domain tests run against both fake and real K8s backends.  The fake
backend pre-provisions IngressClass + cert-manager in-memory.  The real
backend relies on these already being installed in the cluster.

Tests that manipulate FakeK8sClient internals (``_store``, ``_namespaces``,
``_ingress_classes``) are marked ``@pytest.mark.fake_only`` and are
automatically skipped when ``--backend real`` is selected.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import pytest

from kuberoku.factory import KuberokuFactory
from tests.backends.fake import FakeK8sClient

if TYPE_CHECKING:
    from collections.abc import Iterator

# Same constants as root conftest — keeps label selectors consistent.
_TEST_RESOURCE_PREFIX = "k8ut"
_TEST_LABEL_DOMAIN = "test.kuberoku.com"


# ── Marker handling ──────────────────────────────────────────────
def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None:
    """Skip ``@pytest.mark.fake_only`` tests when ``--backend=real``."""
    if config.getoption("--backend", default="fake") != "real":
        return
    skip = pytest.mark.skip(reason="Test requires FakeK8sClient internals")
    for item in items:
        if "fake_only" in item.keywords:
            item.add_marker(skip)


# ── Fixtures ─────────────────────────────────────────────────────
@pytest.fixture()
def k8s(request: pytest.FixtureRequest) -> Any:
    """K8s client for direct resource inspection in domain tests.

    Fake:  FakeK8sClient with nginx IngressClass + cert-manager.
    Real:  RealK8sClient (error-normalizing wrapper over real cluster).
    """
    backend = request.config.getoption("--backend", default="fake")

    if backend == "real":
        from tests.backends.real import RealK8sClient

        return RealK8sClient()

    # Fake backend: create in-memory client with infra pre-provisioned.
    client = FakeK8sClient()
    client.create_ingress_class(
        {
            "apiVersion": "networking.k8s.io/v1",
            "kind": "IngressClass",
            "metadata": {"name": "nginx"},
            "spec": {"controller": "k8s.io/ingress-nginx"},
        }
    )
    client.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"}]},
                },
            },
        },
    )
    return client


@pytest.fixture()
def factory(
    request: pytest.FixtureRequest, k8s: Any, tmp_namespace: str
) -> Iterator[KuberokuFactory]:
    """KuberokuFactory wired to the correct backend.

    Fake:  Uses the ``k8s`` fixture (FakeK8sClient).
    Real:  Uses K8sClient.from_context() with test-safe prefix/domain.
           Cleans up all managed resources after each test.
    """
    backend = request.config.getoption("--backend", default="fake")

    if backend == "real":
        from kuberoku.k8s.client import K8sClient
        from tests.conftest import _wipe_namespace_resources

        yield KuberokuFactory(
            k8s_client=K8sClient.from_context(),
            namespace=tmp_namespace,
            resource_prefix=_TEST_RESOURCE_PREFIX,
            label_domain=_TEST_LABEL_DOMAIN,
        )
        _wipe_namespace_resources(tmp_namespace)
    else:
        yield KuberokuFactory(k8s_client=k8s, namespace=tmp_namespace)


@pytest.fixture()
def app_with_web(factory: KuberokuFactory) -> str:
    """Create an app with a deployed web process type."""
    app_name = "myapp"
    factory.apps.create(app_name)
    factory.deploy.deploy(app_name, image="myapp:v1", wait=False)
    return app_name
