"""
Integration tests for photo upload workflow.

These tests verify the complete workflow of photo uploads including
validation, processing, and moderation.
"""

from unittest.mock import Mock, patch

import pytest
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase

from apps.parks.models import ParkPhoto
from apps.parks.services.media_service import ParkMediaService
from tests.factories import (
    ParkFactory,
    ParkPhotoFactory,
    RideFactory,
    RidePhotoFactory,
    StaffUserFactory,
    UserFactory,
)


@pytest.mark.django_db
class TestParkPhotoUploadWorkflow(TestCase):
    """Integration tests for park photo upload workflow."""

    @patch("apps.parks.services.media_service.MediaService.validate_image_file")
    @patch("apps.parks.services.media_service.MediaService.process_image")
    @patch("apps.parks.services.media_service.MediaService.generate_default_caption")
    @patch("apps.parks.services.media_service.MediaService.extract_exif_date")
    def test__upload_photo__creates_pending_photo(self, mock_exif, mock_caption, mock_process, mock_validate):
        """Test uploading photo creates a pending photo."""
        mock_validate.return_value = (True, None)
        mock_process.return_value = Mock()
        mock_caption.return_value = "Photo by testuser"
        mock_exif.return_value = None

        park = ParkFactory()
        user = UserFactory()
        image = SimpleUploadedFile("test.jpg", b"image data", content_type="image/jpeg")

        photo = ParkMediaService.upload_photo(
            park=park,
            image_file=image,
            user=user,
            caption="Test photo",
            auto_approve=False,
        )

        assert photo.is_approved is False
        assert photo.uploaded_by == user
        assert photo.park == park

    @patch("apps.parks.services.media_service.MediaService.validate_image_file")
    @patch("apps.parks.services.media_service.MediaService.process_image")
    @patch("apps.parks.services.media_service.MediaService.generate_default_caption")
    @patch("apps.parks.services.media_service.MediaService.extract_exif_date")
    def test__upload_photo__auto_approve__creates_approved_photo(
        self, mock_exif, mock_caption, mock_process, mock_validate
    ):
        """Test uploading photo with auto_approve creates approved photo."""
        mock_validate.return_value = (True, None)
        mock_process.return_value = Mock()
        mock_caption.return_value = "Photo by testuser"
        mock_exif.return_value = None

        park = ParkFactory()
        user = UserFactory()
        image = SimpleUploadedFile("test.jpg", b"image data", content_type="image/jpeg")

        photo = ParkMediaService.upload_photo(
            park=park,
            image_file=image,
            user=user,
            auto_approve=True,
        )

        assert photo.is_approved is True


@pytest.mark.django_db
class TestPhotoModerationWorkflow(TestCase):
    """Integration tests for photo moderation workflow."""

    def test__approve_photo__marks_as_approved(self):
        """Test approving a photo marks it as approved."""
        photo = ParkPhotoFactory(is_approved=False)
        moderator = StaffUserFactory()

        result = ParkMediaService.approve_photo(photo, moderator)

        photo.refresh_from_db()
        assert result is True
        assert photo.is_approved is True

    def test__bulk_approve_photos__approves_all(self):
        """Test bulk approving photos approves all photos."""
        park = ParkFactory()
        photos = [
            ParkPhotoFactory(park=park, is_approved=False),
            ParkPhotoFactory(park=park, is_approved=False),
            ParkPhotoFactory(park=park, is_approved=False),
        ]
        moderator = StaffUserFactory()

        count = ParkMediaService.bulk_approve_photos(photos, moderator)

        assert count == 3
        for photo in photos:
            photo.refresh_from_db()
            assert photo.is_approved is True


@pytest.mark.django_db
class TestPrimaryPhotoWorkflow(TestCase):
    """Integration tests for primary photo workflow."""

    def test__set_primary_photo__unsets_previous_primary(self):
        """Test setting primary photo unsets previous primary."""
        park = ParkFactory()
        old_primary = ParkPhotoFactory(park=park, is_primary=True)
        new_primary = ParkPhotoFactory(park=park, is_primary=False)

        result = ParkMediaService.set_primary_photo(park, new_primary)

        old_primary.refresh_from_db()
        new_primary.refresh_from_db()

        assert result is True
        assert old_primary.is_primary is False
        assert new_primary.is_primary is True

    def test__get_primary_photo__returns_correct_photo(self):
        """Test get_primary_photo returns the primary photo."""
        park = ParkFactory()
        ParkPhotoFactory(park=park, is_primary=False, is_approved=True)
        primary = ParkPhotoFactory(park=park, is_primary=True, is_approved=True)
        ParkPhotoFactory(park=park, is_primary=False, is_approved=True)

        result = ParkMediaService.get_primary_photo(park)

        assert result == primary


@pytest.mark.django_db
class TestPhotoStatsWorkflow(TestCase):
    """Integration tests for photo statistics workflow."""

    def test__get_photo_stats__returns_accurate_counts(self):
        """Test get_photo_stats returns accurate statistics."""
        park = ParkFactory()

        # Create various photos
        ParkPhotoFactory(park=park, is_approved=True)
        ParkPhotoFactory(park=park, is_approved=True)
        ParkPhotoFactory(park=park, is_approved=False)
        ParkPhotoFactory(park=park, is_approved=True, is_primary=True)

        stats = ParkMediaService.get_photo_stats(park)

        assert stats["total_photos"] == 4
        assert stats["approved_photos"] == 3
        assert stats["pending_photos"] == 1
        assert stats["has_primary"] is True


@pytest.mark.django_db
class TestPhotoDeleteWorkflow(TestCase):
    """Integration tests for photo deletion workflow."""

    def test__delete_photo__removes_photo(self):
        """Test deleting a photo removes it from database."""
        photo = ParkPhotoFactory()
        photo_id = photo.pk
        moderator = StaffUserFactory()

        result = ParkMediaService.delete_photo(photo, moderator)

        assert result is True
        assert not ParkPhoto.objects.filter(pk=photo_id).exists()

    def test__delete_primary_photo__removes_primary(self):
        """Test deleting primary photo removes primary status."""
        park = ParkFactory()
        primary = ParkPhotoFactory(park=park, is_primary=True)
        moderator = StaffUserFactory()

        ParkMediaService.delete_photo(primary, moderator)

        # Park should no longer have a primary photo
        result = ParkMediaService.get_primary_photo(park)
        assert result is None


@pytest.mark.django_db
class TestRidePhotoWorkflow(TestCase):
    """Integration tests for ride photo workflow."""

    def test__ride_photo__includes_park_info(self):
        """Test ride photo includes park information."""
        ride = RideFactory()
        photo = RidePhotoFactory(ride=ride)

        # Photo should have access to park through ride
        assert photo.ride.park is not None
        assert photo.ride.park.name is not None

    def test__ride_photo__different_types(self):
        """Test ride photos can have different types."""
        ride = RideFactory()

        RidePhotoFactory(ride=ride, photo_type="exterior")
        RidePhotoFactory(ride=ride, photo_type="queue")
        RidePhotoFactory(ride=ride, photo_type="onride")

        assert ride.photos.filter(photo_type="exterior").count() == 1
        assert ride.photos.filter(photo_type="queue").count() == 1
        assert ride.photos.filter(photo_type="onride").count() == 1
