"""
Shared media service for ThrillWiki.

This module provides shared functionality for media upload, storage, and processing
that can be used across all domain-specific media implementations.
"""

import logging
import os
from datetime import datetime
from typing import Any

from django.conf import settings
from django.core.files.uploadedfile import UploadedFile
from PIL import ExifTags, Image

from apps.core.utils import capture_and_log

logger = logging.getLogger(__name__)


class MediaService:
    """Shared service for media upload and processing operations."""

    @staticmethod
    def generate_upload_path(domain: str, identifier: str, filename: str, subdirectory: str | None = None) -> str:
        """
        Generate standardized upload path for media files.

        Args:
            domain: Domain type (e.g., 'park', 'ride')
            identifier: Object identifier (slug or id)
            filename: Original filename
            subdirectory: Optional subdirectory for organization

        Returns:
            Standardized upload path
        """
        # Always use .jpg extension for consistency
        base_filename = f"{identifier}.jpg"

        if subdirectory:
            return f"{domain}/{subdirectory}/{identifier}/{base_filename}"
        else:
            return f"{domain}/{identifier}/{base_filename}"

    @staticmethod
    def extract_exif_date(image_file: UploadedFile) -> datetime | None:
        """
        Extract the date taken from image EXIF data.

        Args:
            image_file: Uploaded image file

        Returns:
            DateTime when photo was taken, or None if not available
        """
        try:
            with Image.open(image_file) as img:
                exif = img.getexif()
                if exif:
                    # Find the DateTime tag ID
                    for tag_id in ExifTags.TAGS:
                        if ExifTags.TAGS[tag_id] == "DateTimeOriginal" and tag_id in exif:
                            # EXIF dates are typically in format: '2024:02:15 14:30:00'
                            date_str = exif[tag_id]
                            return datetime.strptime(date_str, "%Y:%m:%d %H:%M:%S")
            return None
        except Exception as e:
            logger.warning(f"Failed to extract EXIF date: {str(e)}")
            return None

    @staticmethod
    def validate_image_file(image_file: UploadedFile) -> tuple[bool, str | None]:
        """
        Validate uploaded image file.

        Args:
            image_file: Uploaded image file

        Returns:
            Tuple of (is_valid, error_message)
        """
        try:
            # Check file size
            max_size = getattr(settings, "MAX_PHOTO_SIZE", 10 * 1024 * 1024)  # 10MB default
            if image_file.size > max_size:
                return (
                    False,
                    f"File size too large. Maximum size is {max_size // (1024 * 1024)}MB",
                )

            # Check file type
            allowed_types = getattr(
                settings,
                "ALLOWED_PHOTO_TYPES",
                ["image/jpeg", "image/png", "image/webp"],
            )
            if image_file.content_type not in allowed_types:
                return (
                    False,
                    f"File type not allowed. Allowed types: {', '.join(allowed_types)}",
                )

            # Try to open with PIL to validate it's a real image
            with Image.open(image_file) as img:
                img.verify()

            return True, None

        except Exception as e:
            return False, f"Invalid image file: {str(e)}"

    @staticmethod
    def process_image(
        image_file: UploadedFile,
        max_width: int = 1920,
        max_height: int = 1080,
        quality: int = 85,
    ) -> UploadedFile:
        """
        Process and optimize image file.

        Args:
            image_file: Original uploaded file
            max_width: Maximum width for resizing
            max_height: Maximum height for resizing
            quality: JPEG quality (1-100)

        Returns:
            Processed image file
        """
        try:
            with Image.open(image_file) as img:
                # Convert to RGB if necessary
                if img.mode in ("RGBA", "LA", "P"):
                    img = img.convert("RGB")

                # Resize if necessary
                if img.width > max_width or img.height > max_height:
                    img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)

                # Save processed image
                from io import BytesIO

                from django.core.files.uploadedfile import InMemoryUploadedFile

                output = BytesIO()
                img.save(output, format="JPEG", quality=quality, optimize=True)
                output.seek(0)

                return InMemoryUploadedFile(
                    output,
                    "ImageField",
                    f"{os.path.splitext(image_file.name)[0]}.jpg",
                    "image/jpeg",
                    output.getbuffer().nbytes,
                    None,
                )

        except Exception as e:
            logger.warning(f"Failed to process image, using original: {str(e)}")
            return image_file

    @staticmethod
    def generate_default_caption(username: str) -> str:
        """
        Generate default caption for uploaded photos.

        Args:
            username: Username of uploader

        Returns:
            Default caption string
        """
        from django.utils import timezone

        current_time = timezone.now()
        return f"Uploaded by {username} on {current_time.strftime('%B %d, %Y at %I:%M %p')}"

    @staticmethod
    def get_storage_stats() -> dict[str, Any]:
        """
        Get media storage statistics.

        Returns:
            Dictionary with storage statistics
        """
        try:
            # This would need to be implemented based on your storage backend
            return {
                "total_files": 0,
                "total_size_bytes": 0,
                "storage_backend": "default",
                "available_space": "unknown",
            }
        except Exception as e:
            capture_and_log(e, 'Get storage stats', source='service', severity='low')
            return {"error": str(e)}
