"""
Tests de sécurité — Settings (SMTP)
Vérifie :
  - Le mot de passe SMTP est absent des réponses GET (write_only)
  - Authentification requise
"""

from django.test import TestCase, override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
from rest_framework_simplejwt.tokens import RefreshToken

from Auth.models import Profile, ProfileRole
from Establishment.models import Establishment
from Settings.models import SMTPSettings


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def create_user_with_role(email):
    user = Profile.objects.create_user(
        username=email, email=email, password="TestPass!123"
    )
    est = Establishment.objects.create(
        name=f"Ecole {email}", address="1 rue Test",
        total_capacity=50, establishment_type=[1]
    )
    ProfileRole.objects.create(
        profile=user, role_type=ProfileRole.RoleType.PROFIL_ADMIN,
        establishment=est, is_active=True
    )
    return user, est


OVERRIDE = dict(
    CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}},
    SESSION_ENGINE='django.contrib.sessions.backends.db',
)


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------

@override_settings(**OVERRIDE)
class SMTPSettingsAuthTest(TestCase):
    """Authentification requise sur l'endpoint SMTP."""

    def setUp(self):
        self.client = APIClient()
        self.url = reverse('Settings:smtp_settings')

    def test_sans_auth_retourne_401(self):
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


@override_settings(**OVERRIDE)
class SMTPPasswordNotExposedTest(TestCase):
    """
    Le mot de passe SMTP ne doit jamais apparaître dans les réponses GET.
    Avant la correction, smtp_password était retourné en clair à tout
    utilisateur authentifié (incluant les parents).
    """

    def setUp(self):
        self.client = APIClient()
        self.url = reverse('Settings:smtp_settings')
        self.user, self.est = create_user_with_role('smtp_test@test.com')
        SMTPSettings.objects.create(
            establishment=self.est,
            smtp_server='smtp.example.com',
            smtp_port=587,
            smtp_user='user@example.com',
            smtp_password='super_secret_password_123',
            use_tls=True,
        )

    def test_smtp_password_absent_de_la_reponse(self):
        """
        GET /settings/smtp/ ne doit pas retourner smtp_password.
        """
        token = str(RefreshToken.for_user(self.user).access_token)
        self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')
        response = self.client.get(self.url, {'establishment_id': self.est.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        data = response.json()
        # Le mot de passe ne doit pas être dans la réponse (write_only)
        self.assertNotIn(
            'smtp_password', data,
            "smtp_password ne doit pas être exposé dans les réponses API (OWASP A02 - Cryptographic Failures)"
        )
        # Vérification supplémentaire : la valeur secrète n'est pas dans la réponse brute
        self.assertNotIn('super_secret_password_123', response.content.decode())

    def test_smtp_password_accepte_en_ecriture(self):
        """
        POST /settings/smtp/ doit accepter smtp_password (write_only ne bloque pas l'écriture).
        """
        token = str(RefreshToken.for_user(self.user).access_token)
        self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')
        payload = {
            'establishment': self.est.id,
            'smtp_server': 'smtp.newserver.com',
            'smtp_port': 465,
            'smtp_user': 'new@example.com',
            'smtp_password': 'nouveau_mot_de_passe',
            'use_tls': False,
            'use_ssl': True,
        }
        from rest_framework.test import APIRequestFactory
        response = self.client.post(self.url, data=payload, format='json')
        self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_201_CREATED])
