"""
Ride-specific media service for ThrillWiki.

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

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 Ride, RidePhoto

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


class RideMediaService:
    """Service for managing ride-specific media operations."""

    @staticmethod
    def upload_photo(
        ride: Ride,
        image_file: UploadedFile,
        user: User,
        caption: str = "",
        alt_text: str = "",
        photo_type: str = "exterior",
        is_primary: bool = False,
        auto_approve: bool = False,
    ) -> RidePhoto:
        """
        Upload a photo for a ride.

        Args:
            ride: Ride instance
            image_file: Uploaded image file
            user: User uploading the photo
            caption: Photo caption
            alt_text: Alt text for accessibility
            photo_type: Type of photo (exterior, queue, station, etc.)
            is_primary: Whether this should be the primary photo
            auto_approve: Whether to auto-approve the photo

        Returns:
            Created RidePhoto 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 = RidePhoto(
                ride=ride,
                image=processed_image,
                caption=caption or MediaService.generate_default_caption(user.username),
                alt_text=alt_text,
                photo_type=photo_type,
                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 ride {ride.slug} by user {user.username}")
            return photo

    @staticmethod
    def get_ride_photos(
        ride: Ride,
        approved_only: bool = True,
        primary_first: bool = True,
        photo_type: str | None = None,
    ) -> list[RidePhoto]:
        """
        Get photos for a ride.

        Args:
            ride: Ride instance
            approved_only: Whether to only return approved photos
            primary_first: Whether to order primary photos first
            photo_type: Filter by photo type (optional)

        Returns:
            List of RidePhoto instances
        """
        queryset = ride.photos.all()

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

        if photo_type:
            queryset = queryset.filter(photo_type=photo_type)

        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(ride: Ride) -> RidePhoto | None:
        """
        Get the primary photo for a ride.

        Args:
            ride: Ride instance

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

    @staticmethod
    def get_photos_by_type(ride: Ride, photo_type: str) -> list[RidePhoto]:
        """
        Get photos of a specific type for a ride.

        Args:
            ride: Ride instance
            photo_type: Type of photos to retrieve

        Returns:
            List of RidePhoto instances
        """
        return list(ride.photos.filter(photo_type=photo_type, is_approved=True).order_by("-created_at"))

    @staticmethod
    def set_primary_photo(ride: Ride, photo: RidePhoto) -> bool:
        """
        Set a photo as the primary photo for a ride.

        Args:
            ride: Ride instance
            photo: RidePhoto to set as primary

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

        with transaction.atomic():
            # Unset current primary
            ride.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 ride {ride.slug}")
            return True

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

        Args:
            photo: RidePhoto 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 ride photo {photo.pk}', source='service')
            return False

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

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

        Returns:
            True if successful, False otherwise
        """
        try:
            ride_slug = photo.ride.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 ride {ride_slug} by user {deleted_by.username}")
            return True
        except Exception as e:
            capture_and_log(e, f'Delete ride photo {photo.pk}', source='service')
            return False

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

        Args:
            ride: Ride instance

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

        # Get counts by photo type
        type_counts = {}
        for photo_type, _ in RidePhoto._meta.get_field("photo_type").choices:
            type_counts[photo_type] = photos.filter(photo_type=photo_type).count()

        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(),
            "by_type": type_counts,
        }

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

        Args:
            photos: List of RidePhoto 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 RideMediaService.approve_photo(photo, approved_by):
                    approved_count += 1

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

    @staticmethod
    def get_construction_timeline(ride: Ride) -> list[RidePhoto]:
        """
        Get construction photos ordered chronologically.

        Args:
            ride: Ride instance

        Returns:
            List of construction RidePhoto instances ordered by date taken
        """
        return list(
            ride.photos.filter(photo_type="construction", is_approved=True).order_by("date_taken", "created_at")
        )

    @staticmethod
    def get_onride_photos(ride: Ride) -> list[RidePhoto]:
        """
        Get on-ride photos for a ride.

        Args:
            ride: Ride instance

        Returns:
            List of on-ride RidePhoto instances
        """
        return RideMediaService.get_photos_by_type(ride, "onride")
