"""Base-package tests: the storm-safe view softens unexpected errors but lets DRF exceptions
through; the fail-open-if-unconfigured permission; and /health (liveness + deep-check)."""
from django.test import override_settings
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory

from andrea_svc_web.health import HealthView
from andrea_svc_web.permissions import ServiceKeyRequiredIfConfigured
from andrea_svc_web.views import StormSafeAPIView

rf = APIRequestFactory()


# ── StormSafeAPIView ──────────────────────────────────────────────────────────────────────────
class _Boom(StormSafeAPIView):
    authentication_classes: list = []
    permission_classes: list = []

    def post(self, request):
        raise RuntimeError("kaboom")


class _Validation(StormSafeAPIView):
    authentication_classes: list = []
    permission_classes: list = []

    def post(self, request):
        raise ValidationError("bad field")


def test_unexpected_error_is_softened_to_200():
    resp = _Boom.as_view()(rf.post("/x", {}, format="json"))
    assert resp.status_code == 200
    assert resp.data["ok"] is False
    assert "kaboom" in resp.data["error"]


def test_drf_exception_still_propagates():
    resp = _Validation.as_view()(rf.post("/x", {}, format="json"))
    assert resp.status_code == 400          # DRF ValidationError is NOT softened


# ── FastAPI-compat 422 toggle ───────────────────────────────────────────────────────────────────
def test_fastapi_compat_422_off_is_standard_400():
    resp = _Validation.as_view()(rf.post("/x", {}, format="json"))
    assert resp.status_code == 400          # default: DRF standard 400


def test_fastapi_compat_422_on_renders_detail_shape():
    with override_settings(ANDREA_FASTAPI_COMPAT_422=True):
        resp = _Validation.as_view()(rf.post("/x", {}, format="json"))
    assert resp.status_code == 422
    assert isinstance(resp.data.get("detail"), list) and resp.data["detail"]
    assert set(resp.data["detail"][0]) >= {"loc", "msg", "type"}


# ── ServiceKeyRequiredIfConfigured ──────────────────────────────────────────────────────────────
class _Princ:
    is_authenticated = True


def test_permission_open_when_unconfigured():
    perm = ServiceKeyRequiredIfConfigured()
    req = rf.post("/x")
    req.user = None
    with override_settings(ANDREA_SVC_KEYS=None, OIDC_ISSUER="", OIDC_JWKS_URL=""):
        assert perm.has_permission(req, None) is True          # dev/unconfigured => open


def test_permission_closed_when_configured_and_no_principal():
    perm = ServiceKeyRequiredIfConfigured()
    req = rf.post("/x")
    req.user = None
    with override_settings(ANDREA_SVC_KEYS="secret"):
        assert perm.has_permission(req, None) is False         # configured + no cred => deny


def test_permission_allows_authenticated_when_configured():
    perm = ServiceKeyRequiredIfConfigured()
    req = rf.post("/x")
    req.user = _Princ()
    with override_settings(ANDREA_SVC_KEYS="secret"):
        assert perm.has_permission(req, None) is True


# ── HealthView ────────────────────────────────────────────────────────────────────────────────
def test_health_liveness_ok():
    resp = HealthView.as_view()(rf.get("/health"))
    assert resp.status_code == 200
    assert resp.data["status"] == "ok"
    assert resp.data["service"] == "test-svc"


def test_health_deep_check_degraded(monkeypatch):
    import andrea_svc_web.health as h
    monkeypatch.setattr(h, "_run_check", lambda: False)
    resp = HealthView.as_view()(rf.get("/health"))
    assert resp.status_code == 503
    assert resp.data["status"] == "degraded"
