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
from posts.models import Post
from videos.models import Video

User = get_user_model()

class PostVideoTestCase(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(
            username='testuser',
            email='test@example.com',
            password='testpass123'
        )
        self.client.force_authenticate(user=self.user)

    def create_test_video(self, name='test_video.mp4'):
        """Helper method to create a test video file"""
        return SimpleUploadedFile(
            name,
            b'fake-video-content',
            content_type='video/mp4'
        )

    def test_upload_video_endpoint(self):
        """Test the standalone video upload endpoint"""
        video_file = self.create_test_video()
        response = self.client.post(reverse('upload_video'), {'file': video_file}, format='multipart')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertIn('id', response.data)
        self.assertIn('file', response.data)
        self.assertIn('url', response.data)
        self.assertEqual(Video.objects.count(), 1)

    def test_create_post_with_videos(self):
        """Test creating a post with video files"""
        video1 = self.create_test_video('video1.mp4')
        video2 = self.create_test_video('video2.mp4')

        post_data = {
            'content': 'Post with videos',
            'videos': [video1, video2],
            'video_order': ['new_0', 'new_1']
        }

        response = self.client.post(reverse('create_post'), post_data, format='multipart')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(len(response.data['videos']), 2)
        self.assertEqual(Post.objects.get(id=response.data['id']).videos.count(), 2)

    def test_create_post_mixed_media(self):
        """Test creating a post with both images and videos"""
        from io import BytesIO
        from PIL import Image as PILImage

        # Create test image
        image_io = BytesIO()
        PILImage.new('RGB', (100, 100)).save(image_io, format='JPEG')
        image_file = SimpleUploadedFile('test.jpg', image_io.getvalue(), content_type='image/jpeg')

        # Create test video
        video_file = self.create_test_video()

        post_data = {
            'content': 'Mixed media post',
            'images': [image_file],
            'videos': [video_file]
        }

        response = self.client.post(reverse('create_post'), post_data, format='multipart')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(len(response.data['images']), 1)
        self.assertEqual(len(response.data['videos']), 1)

    def test_update_post_remove_add_videos(self):
        """Test updating a post by removing and adding videos"""
        # 1. Create post with one video
        video1_obj = Video.objects.create(
            file=self.create_test_video('v1.mp4'),
            created_by=self.user
        )
        post = Post.objects.create(content='Initial', created_by=self.user)
        from posts.models import PostVideo
        PostVideo.objects.create(post=post, video=video1_obj, order=0)

        # 2. Update post: remove video1 and add video2
        video2_file = self.create_test_video('v2.mp4')
        update_data = {
            'content': 'Updated',
            'remove_videos': [video1_obj.id],
            'videos': [video2_file],
            'video_order': ['new_0']
        }

        response = self.client.put(reverse('update_post', args=[post.id]), update_data, format='multipart')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['videos']), 1)
        # Ensure only the new video remains
        post.refresh_from_db()
        self.assertEqual(post.videos.count(), 1)
        self.assertNotEqual(post.videos.first().id, video1_obj.id)

    def test_post_requires_content_or_media(self):
        """Test that a post cannot be empty (no content, no images, no videos)"""
        post_data = {
            'content': '',
            'images': [],
            'videos': []
        }
        response = self.client.post(reverse('create_post'), post_data, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

        # Should work with just a video
        post_data['videos'] = [self.create_test_video()]
        response = self.client.post(reverse('create_post'), post_data, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
