from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient
from rest_framework import status
from django.urls import reverse
from django.core.files.uploadedfile import SimpleUploadedFile
import io
from PIL import Image

User = get_user_model()


class ImageTestCase(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(
            username='testuser',
            email='test@example.com',
            password='testpass123'
        )
        self.user2 = User.objects.create_user(
            username='user2',
            email='user2@example.com',
            password='user2pass123'
        )
        from posts.models import Post
        self.post = Post.objects.create(
            content='Test post',
            created_by=self.user
        )

    def create_test_image(self):
        """Helper method to create a test image"""
        # Créer une image en mémoire avec PIL
        image = Image.new('RGB', (100, 100), 'red')
        image_io = io.BytesIO()
        image.save(image_io, format='JPEG')
        image_io.seek(0)

        # Créer un SimpleUploadedFile avec le contenu de l'image
        return SimpleUploadedFile(
            'test_image.jpg',
            image_io.getvalue(),
            content_type='image/jpeg'
        )

    def test_create_image(self):
        """Test creating an image"""
        self.client.force_authenticate(user=self.user)

        # Utiliser la méthode helper pour créer une image valide
        image = self.create_test_image()
        data = {
            'image': image
        }

        response = self.client.post(reverse('create_image'), data, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_create_image_unauthenticated(self):
        """Test creating an image without authentication"""
        image_file = self.create_test_image()
        data = {
            'image': image_file
        }
        response = self.client.post(reverse('create_image'), data, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_list_images(self):
        """Test listing images"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post si nécessaire pour le test
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_images'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_image_detail(self):
        """Test viewing image details"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post si nécessaire pour le test
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('image_detail', args=[image.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_delete_image(self):
        """Test deleting an image"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post si nécessaire pour le test
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user)
        response = self.client.delete(reverse('delete_image', args=[image.id]))
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

    def test_delete_image_unauthorized(self):
        """Test deleting an image by non-creator"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post si nécessaire pour le test
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user2)
        response = self.client.delete(reverse('delete_image', args=[image.id]))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_post_images(self):
        """Test listing images for a specific post"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('post_images', args=[self.post.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_user_images(self):
        """Test listing images for a specific user"""
        from images.models import Image
        image_file = self.create_test_image()
        # Créer l'image sans le paramètre 'post'
        image = Image.objects.create(
            image=image_file,
            created_by=self.user
        )
        # Ajouter l'image au post si nécessaire pour le test
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('user_images', args=[self.user.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_add_images_to_post(self):
        """Test adding images to an existing post"""
        self.client.force_authenticate(user=self.user)

        # Créer des images
        image1 = self.create_test_image()
        image2 = self.create_test_image()

        data = {
            'images': [image1, image2]
        }

        response = self.client.post(
            reverse('add_images_to_post', args=[self.post.id]),
            data,
            format='multipart'
        )
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        # Vérifier que les images ont été ajoutées au post
        self.post.refresh_from_db()
        self.assertEqual(self.post.images.count(), 2)

    def test_remove_image_from_post(self):
        """Test removing an image from a post"""
        from images.models import Image

        self.client.force_authenticate(user=self.user)

        # Créer une image et l'ajouter au post
        image_file = self.create_test_image()
        image = Image.objects.create(image=image_file, created_by=self.user)
        from posts.models import PostImage
        PostImage.objects.create(post=self.post, image=image, order=0)

        response = self.client.delete(reverse('remove_image_from_post', args=[image.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Vérifier que l'image a été retirée du post
        self.post.refresh_from_db()
        self.assertEqual(self.post.images.count(), 0)