"""Tests for AddonsService.create — postgres, redis, custom resources."""

from __future__ import annotations

import pytest

from kuberoku.exceptions import (
    AddonAlreadyExistsError,
    AddonTypeNotSupportedError,
    AppNotFoundError,
    KuberokuError,
)
from kuberoku.factory import KuberokuFactory
from kuberoku.k8s.resources import safe_name


def test_create_postgres(app_factory: KuberokuFactory) -> None:
    addon = app_factory.addons.create("myapp", "postgres")
    assert addon.addon_type == "postgres"
    assert addon.instance_name == "postgres"
    assert addon.status == "running"
    assert addon.env_key == "DATABASE_URL"
    assert addon.external is False
    assert addon.ephemeral is False


def test_create_redis(app_factory: KuberokuFactory) -> None:
    addon = app_factory.addons.create("myapp", "redis")
    assert addon.addon_type == "redis"
    assert addon.instance_name == "redis"
    assert addon.status == "running"
    assert addon.env_key == "REDIS_URL"


def test_create_creates_statefulset(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    sts_name = safe_name(app_factory.prefix, "addon", "myapp-postgres")
    sts = app_factory.k8s.get_statefulset(app_factory.namespace, sts_name)
    container = sts["spec"]["template"]["spec"]["containers"][0]
    assert container["image"] == "postgres:16"
    assert container["ports"][0]["containerPort"] == 5432


def test_create_creates_service(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    svc_name = safe_name(app_factory.prefix, "addon", "myapp-postgres")
    svc = app_factory.k8s.get_service(app_factory.namespace, svc_name)
    assert svc["spec"]["type"] == "ClusterIP"
    assert svc["spec"]["ports"][0]["port"] == 5432


def test_create_creates_network_policy(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    np_name = safe_name(app_factory.prefix, "netpol-allow", "myapp-postgres")
    np = app_factory.k8s.get_network_policy(app_factory.namespace, np_name)
    assert np["spec"]["policyTypes"] == ["Ingress"]
    assert np["spec"]["ingress"][0]["ports"][0]["port"] == 5432


def test_create_creates_credential_secret(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    secret_name = safe_name(app_factory.prefix, "addon-secret", "myapp-postgres")
    secret = app_factory.k8s.get_secret(app_factory.namespace, secret_name)
    assert "username" in secret["data"]
    assert "password" in secret["data"]
    assert "database" in secret["data"]
    assert secret["data"]["username"] == "kuberoku"


def test_create_creates_metadata_configmap(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    cm_name = safe_name(app_factory.prefix, "addon-meta", "myapp-postgres")
    cm = app_factory.k8s.get_configmap(app_factory.namespace, cm_name)
    assert cm["data"]["type"] == "postgres"
    assert cm["data"]["status"] == "running"


def test_create_injects_config_url(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    config = app_factory.config.list("myapp")
    assert "DATABASE_URL" in config
    assert "postgres://" in config["DATABASE_URL"]


def test_create_custom_resources(app_factory: KuberokuFactory) -> None:
    addon = app_factory.addons.create("myapp", "postgres", cpu="500m", memory="512Mi")
    assert addon.cpu == "500m"
    assert addon.memory == "512Mi"
    sts_name = safe_name(app_factory.prefix, "addon", "myapp-postgres")
    sts = app_factory.k8s.get_statefulset(app_factory.namespace, sts_name)
    container = sts["spec"]["template"]["spec"]["containers"][0]
    assert container["resources"]["requests"]["cpu"] == "500m"
    assert container["resources"]["limits"]["cpu"] == "500m"


def test_create_guaranteed_qos(app_factory: KuberokuFactory) -> None:
    """Guaranteed QoS: requests = limits by default."""
    app_factory.addons.create("myapp", "postgres", cpu="250m", memory="256Mi")
    sts_name = safe_name(app_factory.prefix, "addon", "myapp-postgres")
    sts = app_factory.k8s.get_statefulset(app_factory.namespace, sts_name)
    res = sts["spec"]["template"]["spec"]["containers"][0]["resources"]
    assert res["requests"]["cpu"] == "250m"
    assert res["limits"]["cpu"] == "250m"
    assert res["requests"]["memory"] == "256Mi"
    assert res["limits"]["memory"] == "256Mi"


def test_create_duplicate_fails(app_factory: KuberokuFactory) -> None:
    app_factory.addons.create("myapp", "postgres")
    with pytest.raises(AddonAlreadyExistsError):
        app_factory.addons.create("myapp", "postgres")


def test_create_unsupported_type(app_factory: KuberokuFactory) -> None:
    with pytest.raises(AddonTypeNotSupportedError):
        app_factory.addons.create("myapp", "mongodb")


def test_create_app_not_found(app_factory: KuberokuFactory) -> None:
    with pytest.raises(AppNotFoundError):
        app_factory.addons.create("nonexistent", "postgres")


def test_create_on_step(app_factory: KuberokuFactory) -> None:
    steps: list[str] = []
    app_factory.addons.create("myapp", "postgres", on_step=steps.append)
    assert len(steps) > 0
    assert any("metadata" in s.lower() for s in steps)


def test_create_redis_with_requirepass(app_factory: KuberokuFactory) -> None:
    """Redis StatefulSet should have --requirepass command."""
    app_factory.addons.create("myapp", "redis")
    sts_name = safe_name(app_factory.prefix, "addon", "myapp-redis")
    sts = app_factory.k8s.get_statefulset(app_factory.namespace, sts_name)
    container = sts["spec"]["template"]["spec"]["containers"][0]
    assert container["command"][0] == "redis-server"
    assert "--requirepass" in container["command"]


def test_create_postgres_ephemeral_fails(app_factory: KuberokuFactory) -> None:
    """Postgres does not support ephemeral mode."""
    with pytest.raises(KuberokuError, match="requires persistent storage"):
        app_factory.addons.create("myapp", "postgres", ephemeral=True)
