"""
Comprobaciones de salud.

`/health/` responde mientras el proceso este vivo; lo usa el balanceador.
`/health/ready/` comprueba base de datos y cache; lo usa el orquestador para
decidir si mandar trafico.

Ninguno revela versiones, rutas ni cadenas de conexion: son endpoints
publicos y esa informacion solo sirve a quien busca por donde entrar.
"""

from __future__ import annotations

import logging

from django.core.cache import cache
from django.db import connection
from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView

logger = logging.getLogger("notifications.health")


class Liveness(APIView):
    authentication_classes: list = []
    permission_classes = [AllowAny]
    throttle_classes: list = []

    @extend_schema(summary="Comprobacion de vida", responses={200: None}, auth=[])
    def get(self, request, format=None):
        return Response({"status": "ok"}, status=status.HTTP_200_OK)


class Readiness(APIView):
    authentication_classes: list = []
    permission_classes = [AllowAny]
    throttle_classes: list = []

    @extend_schema(
        summary="Comprobacion de dependencias",
        responses={200: None, 503: None},
        auth=[],
    )
    def get(self, request, format=None):
        checks = {"database": _check_database(), "cache": _check_cache()}
        healthy = all(checks.values())

        return Response(
            {"status": "ok" if healthy else "degraded", "checks": checks},
            status=(
                status.HTTP_200_OK if healthy else status.HTTP_503_SERVICE_UNAVAILABLE
            ),
        )


def _check_database() -> bool:
    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
            cursor.fetchone()
        return True
    except Exception:  # noqa: BLE001 - cualquier fallo cuenta como no listo
        logger.exception("La comprobacion de la base de datos fallo")
        return False


def _check_cache() -> bool:
    try:
        cache.set("health:probe", "1", timeout=10)
        return cache.get("health:probe") == "1"
    except Exception:  # noqa: BLE001
        logger.exception("La comprobacion de la cache fallo")
        return False
