"""
Comprobaciones sobre cosas que no se ven en los tests de negocio.

Cada una existe porque falló de verdad: un fichero de arranque que dejó de
exportar lo que Passenger busca, un límite que no protegía lo que decía
proteger, una cuenta desactivada que seguía enviando.
"""

from __future__ import annotations

import importlib.util
from pathlib import Path

import pytest
from django.urls import reverse

from keys.models.access_token import AccessToken
from keys.models.api_keys import ApiKeys

RAIZ = Path(__file__).resolve().parent.parent.parent


def test_el_punto_de_entrada_wsgi_exporta_application():
    """
    `ruff --fix` borró `from core.wsgi import application` de
    `passenger_wsgi.py` por considerarla un import sin usar (commit 336b26d).
    El servicio dejó de arrancar bajo Passenger y nada lo delató: los tests,
    `ruff` y `check --deploy` seguían en verde, porque el fallo era justo la
    ausencia de esa línea.
    """
    ruta = RAIZ / "passenger_wsgi.py"
    spec = importlib.util.spec_from_file_location("passenger_wsgi", ruta)
    modulo = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(modulo)

    assert hasattr(modulo, "application"), (
        "passenger_wsgi.py no exporta `application`: Passenger no puede cargar "
        "la aplicación y el servicio no arranca."
    )


@pytest.mark.django_db
def test_una_cuenta_desactivada_no_autentica(clave_api, cuenta):
    """
    `Account.active` no se comprobaba en ningún punto: desactivar una cuenta
    desde el panel no cortaba nada y sus claves seguían enviando.
    """
    assert ApiKeys.authenticate(clave_api.raw_key) is not None

    cuenta.active = False
    cuenta.save(update_fields=["active"])

    assert ApiKeys.authenticate(clave_api.raw_key) is None


@pytest.mark.django_db
def test_una_cuenta_desactivada_invalida_sus_tokens(api, clave_api, cuenta):
    """La cuenta puede desactivarse después de emitir el token."""
    _, token = AccessToken.issue(clave_api)

    cuenta.active = False
    cuenta.save(update_fields=["active"])

    api.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")
    respuesta = api.post(
        reverse("v1:mail-send"),
        {
            "from_email": "avisos@ejemplo.com",
            "to": ["destino@ejemplo.com"],
            "subject": "S",
            "html": "<p>x</p>",
        },
        format="json",
    )
    assert respuesta.status_code == 401


@pytest.mark.django_db
def test_el_endpoint_de_token_esta_limitado(api, clave_api, settings):
    """
    `TokenIssueThrottle` existía pero no la usaba ninguna vista, y declararla
    sin más tampoco bastaba: DRF autentica antes de limitar, así que un intento
    fallido nunca llegaba a contarse y se podían probar claves sin coste.
    """
    from rest_framework.throttling import SimpleRateThrottle

    original = dict(SimpleRateThrottle.THROTTLE_RATES)
    SimpleRateThrottle.THROTTLE_RATES = {**original, "auth": "3/min"}
    try:
        codigos = []
        for _ in range(10):
            respuesta = api.get("/auth/v1/token/", HTTP_X_API_KEY="ApiKey_no_existe")
            codigos.append(respuesta.status_code)
    finally:
        SimpleRateThrottle.THROTTLE_RATES = original

    assert 429 in codigos, (
        f"Ningún intento fallido llegó a limitarse: {codigos}"
    )


@pytest.mark.django_db
def test_el_limite_de_envios_no_se_comparte_entre_cuentas(clave_api):
    """
    Contaba por `request.user.pk`, y `Account.user` es una clave ajena: dos
    cuentas distintas colgadas del mismo usuario compartían cupo, así que una
    agotaba el límite de la otra.
    """
    from django.contrib.auth import get_user_model

    from authentication.models.account import Account
    from authentication.models.roles import Roles
    from notifications.throttling import SendThrottle

    usuario = get_user_model().objects.create_user(username="compartido", password="x" * 20)
    rol, _ = Roles.objects.get_or_create(description="Sistema")
    # Dos cuentas distintas colgando del MISMO usuario de Django.
    cuenta_a = Account.objects.create(name="A", active=True, rol=rol, user=usuario)
    cuenta_b = Account.objects.create(name="B", active=True, rol=rol, user=usuario)
    clave_a, _ = ApiKeys.issue(cuenta_a, active=True)
    clave_b, _ = ApiKeys.issue(cuenta_b, active=True)

    class PeticionFalsa:
        def __init__(self, clave):
            self.api_key_record = clave
            self.user = usuario
            self.META = {"REMOTE_ADDR": "10.0.0.1"}

    throttle = SendThrottle()
    clave_cache_a = throttle.get_cache_key(PeticionFalsa(clave_a), None)
    clave_cache_b = throttle.get_cache_key(PeticionFalsa(clave_b), None)

    assert clave_cache_a != clave_cache_b, (
        "Dos cuentas distintas comparten contador de límite de envíos."
    )
