"""
Tests unitaires pour le module Common.
Vérifie que les endpoints Domain et Category requièrent une authentification JWT.
"""

import json

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


def create_user(email="common_test@example.com", password="testpassword123"):
    return Profile.objects.create_user(username=email, email=email, password=password)


def get_jwt_token(user):
    refresh = RefreshToken.for_user(user)
    return str(refresh.access_token)


TEST_REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

TEST_CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}


# ---------------------------------------------------------------------------
# Domain
# ---------------------------------------------------------------------------

@override_settings(
    CACHES=TEST_CACHES,
    SESSION_ENGINE='django.contrib.sessions.backends.db',
    REST_FRAMEWORK=TEST_REST_FRAMEWORK,
)
class DomainEndpointAuthTest(TestCase):
    """Tests d'authentification sur les endpoints Domain."""

    def setUp(self):
        self.client = APIClient()
        self.list_url = reverse("Common:domain_list_create")
        self.user = create_user()

    def test_get_domains_sans_auth_retourne_401(self):
        """GET /Common/domains sans token doit retourner 401."""
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_post_domain_sans_auth_retourne_401(self):
        """POST /Common/domains sans token doit retourner 401."""
        response = self.client.post(
            self.list_url,
            data=json.dumps({"name": "Musique"}),
            content_type="application/json",
        )
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_get_domains_avec_auth_retourne_200(self):
        """GET /Common/domains avec token valide doit retourner 200."""
        token = get_jwt_token(self.user)
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_put_domain_sans_auth_retourne_401(self):
        """PUT /Common/domains/{id} sans token doit retourner 401."""
        url = reverse("Common:domain_detail", kwargs={"id": 1})
        response = self.client.put(
            url,
            data=json.dumps({"name": "Danse"}),
            content_type="application/json",
        )
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_delete_domain_sans_auth_retourne_401(self):
        """DELETE /Common/domains/{id} sans token doit retourner 401."""
        url = reverse("Common:domain_detail", kwargs={"id": 1})
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


# ---------------------------------------------------------------------------
# Category
# ---------------------------------------------------------------------------

@override_settings(
    CACHES=TEST_CACHES,
    SESSION_ENGINE='django.contrib.sessions.backends.db',
    REST_FRAMEWORK=TEST_REST_FRAMEWORK,
)
class CategoryEndpointAuthTest(TestCase):
    """Tests d'authentification sur les endpoints Category."""

    def setUp(self):
        self.client = APIClient()
        self.list_url = reverse("Common:category_list_create")
        self.user = create_user(email="category_test@example.com")

    def test_get_categories_sans_auth_retourne_401(self):
        """GET /Common/categories sans token doit retourner 401."""
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_post_category_sans_auth_retourne_401(self):
        """POST /Common/categories sans token doit retourner 401."""
        response = self.client.post(
            self.list_url,
            data=json.dumps({"name": "Jazz"}),
            content_type="application/json",
        )
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_get_categories_avec_auth_retourne_200(self):
        """GET /Common/categories avec token valide doit retourner 200."""
        token = get_jwt_token(self.user)
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_put_category_sans_auth_retourne_401(self):
        """PUT /Common/categories/{id} sans token doit retourner 401."""
        url = reverse("Common:category_detail", kwargs={"id": 1})
        response = self.client.put(
            url,
            data=json.dumps({"name": "Classique"}),
            content_type="application/json",
        )
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_delete_category_sans_auth_retourne_401(self):
        """DELETE /Common/categories/{id} sans token doit retourner 401."""
        url = reverse("Common:category_detail", kwargs={"id": 1})
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
