"""
Park-specific media service for ThrillWiki.

This module provides media management functionality specific to parks.
"""

import logging
from typing import Any

from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import UploadedFile
from django.db import transaction

from apps.core.services.media_service import MediaService
from apps.core.utils import capture_and_log

from ..models import Park, ParkPhoto

User = get_user_model()
logger = logging.getLogger(__name__)


class ParkMediaService:
    """Service for managing park-specific media operations."""

    @staticmethod
    def upload_photo(
        park: Park,
        image_file: UploadedFile,
        user: User,
        caption: str = "",
        alt_text: str = "",
        is_primary: bool = False,
        auto_approve: bool = False,
    ) -> ParkPhoto:
        """
        Upload a photo for a park.

        Args:
            park: Park instance
            image_file: Uploaded image file
            user: User uploading the photo
            caption: Photo caption
            alt_text: Alt text for accessibility
            is_primary: Whether this should be the primary photo
            auto_approve: Whether to auto-approve the photo

        Returns:
            Created ParkPhoto instance

        Raises:
            ValueError: If image validation fails
        """
        # Validate image file
        is_valid, error_message = MediaService.validate_image_file(image_file)
        if not is_valid:
            raise ValueError(error_message)

        # Process image
        processed_image = MediaService.process_image(image_file)

        with transaction.atomic():
            # Create photo instance
            photo = ParkPhoto(
                park=park,
                image=processed_image,
                caption=caption or MediaService.generate_default_caption(user.username),
                alt_text=alt_text,
                is_primary=is_primary,
                is_approved=auto_approve,
                uploaded_by=user,
            )

            # Extract EXIF date
            photo.date_taken = MediaService.extract_exif_date(processed_image)

            photo.save()

            logger.info(f"Photo uploaded for park {park.slug} by user {user.username}")
            return photo

    @staticmethod
    def get_park_photos(park: Park, approved_only: bool = True, primary_first: bool = True) -> list[ParkPhoto]:
        """
        Get photos for a park.

        Args:
            park: Park instance
            approved_only: Whether to only return approved photos
            primary_first: Whether to order primary photos first

        Returns:
            List of ParkPhoto instances
        """
        queryset = park.photos.all()

        if approved_only:
            queryset = queryset.filter(is_approved=True)

        if primary_first:
            queryset = queryset.order_by("-is_primary", "-created_at")
        else:
            queryset = queryset.order_by("-created_at")

        return list(queryset)

    @staticmethod
    def get_primary_photo(park: Park) -> ParkPhoto | None:
        """
        Get the primary photo for a park.

        Args:
            park: Park instance

        Returns:
            Primary ParkPhoto instance or None
        """
        try:
            return park.photos.filter(is_primary=True, is_approved=True).first()
        except ParkPhoto.DoesNotExist:
            return None

    @staticmethod
    def set_primary_photo(park: Park, photo: ParkPhoto) -> bool:
        """
        Set a photo as the primary photo for a park.

        Args:
            park: Park instance
            photo: ParkPhoto to set as primary

        Returns:
            True if successful, False otherwise
        """
        if photo.park != park:
            return False

        with transaction.atomic():
            # Unset current primary
            park.photos.filter(is_primary=True).update(is_primary=False)

            # Set new primary
            photo.is_primary = True
            photo.save()

            logger.info(f"Set photo {photo.pk} as primary for park {park.slug}")
            return True

    @staticmethod
    def approve_photo(photo: ParkPhoto, approved_by: User) -> bool:
        """
        Approve a park photo.

        Args:
            photo: ParkPhoto to approve
            approved_by: User approving the photo

        Returns:
            True if successful, False otherwise
        """
        try:
            photo.is_approved = True
            photo.save()

            logger.info(f"Photo {photo.pk} approved by user {approved_by.username}")
            return True
        except Exception as e:
            capture_and_log(e, f'Approve park photo {photo.pk}', source='service')
            return False

    @staticmethod
    def delete_photo(photo: ParkPhoto, deleted_by: User) -> bool:
        """
        Delete a park photo.

        Args:
            photo: ParkPhoto to delete
            deleted_by: User deleting the photo

        Returns:
            True if successful, False otherwise
        """
        try:
            park_slug = photo.park.slug
            photo_id = photo.pk

            # Delete the file and database record
            if photo.image:
                photo.image.delete(save=False)
            photo.delete()

            logger.info(f"Photo {photo_id} deleted from park {park_slug} by user {deleted_by.username}")
            return True
        except Exception as e:
            capture_and_log(e, f'Delete park photo {photo.pk}', source='service')
            return False

    @staticmethod
    def get_photo_stats(park: Park) -> dict[str, Any]:
        """
        Get photo statistics for a park.

        Args:
            park: Park instance

        Returns:
            Dictionary with photo statistics
        """
        photos = park.photos.all()

        return {
            "total_photos": photos.count(),
            "approved_photos": photos.filter(is_approved=True).count(),
            "pending_photos": photos.filter(is_approved=False).count(),
            "has_primary": photos.filter(is_primary=True).exists(),
            "recent_uploads": photos.order_by("-created_at")[:5].count(),
        }

    @staticmethod
    def bulk_approve_photos(photos: list[ParkPhoto], approved_by: User) -> int:
        """
        Bulk approve multiple photos.

        Args:
            photos: List of ParkPhoto instances to approve
            approved_by: User approving the photos

        Returns:
            Number of photos successfully approved
        """
        approved_count = 0

        with transaction.atomic():
            for photo in photos:
                if ParkMediaService.approve_photo(photo, approved_by):
                    approved_count += 1

        logger.info(f"Bulk approved {approved_count} photos by user {approved_by.username}")
        return approved_count
