"""
Validators for image uploads.
"""

import magic
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
from PIL import Image
from typing import Optional


# Allowed file types
ALLOWED_MIME_TYPES = [
    'image/jpeg',
    'image/jpg',
    'image/png',
    'image/webp',
    'image/gif',
]

ALLOWED_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp', '.gif']

# Size limits (in bytes)
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10 MB
MIN_FILE_SIZE = 1024  # 1 KB

# Dimension limits
MIN_WIDTH = 100
MIN_HEIGHT = 100
MAX_WIDTH = 8000
MAX_HEIGHT = 8000

# Aspect ratio limits (for specific photo types)
ASPECT_RATIO_LIMITS = {
    'banner': {'min': 2.0, 'max': 4.0},  # Wide banners
    'logo': {'min': 0.5, 'max': 2.0},     # Square-ish logos
}


def validate_image_file_type(file: InMemoryUploadedFile | TemporaryUploadedFile) -> None:
    """
    Validate that the uploaded file is an allowed image type.
    
    Uses python-magic to detect actual file type, not just extension.
    
    Args:
        file: The uploaded file object
        
    Raises:
        ValidationError: If file type is not allowed
    """
    # Check file extension
    file_ext = None
    if hasattr(file, 'name') and file.name:
        file_ext = '.' + file.name.split('.')[-1].lower()
        if file_ext not in ALLOWED_EXTENSIONS:
            raise ValidationError(
                f"File extension {file_ext} not allowed. "
                f"Allowed extensions: {', '.join(ALLOWED_EXTENSIONS)}"
            )
    
    # Check MIME type from content type
    if hasattr(file, 'content_type'):
        if file.content_type not in ALLOWED_MIME_TYPES:
            raise ValidationError(
                f"File type {file.content_type} not allowed. "
                f"Allowed types: {', '.join(ALLOWED_MIME_TYPES)}"
            )
    
    # Verify actual file content using python-magic
    try:
        file.seek(0)
        mime = magic.from_buffer(file.read(2048), mime=True)
        file.seek(0)
        
        if mime not in ALLOWED_MIME_TYPES:
            raise ValidationError(
                f"File content type {mime} does not match allowed types. "
                "File may be corrupted or incorrectly labeled."
            )
    except Exception as e:
        # If magic fails, we already validated content_type above
        pass


def validate_image_file_size(file: InMemoryUploadedFile | TemporaryUploadedFile) -> None:
    """
    Validate that the file size is within allowed limits.
    
    Args:
        file: The uploaded file object
        
    Raises:
        ValidationError: If file size is not within limits
    """
    file_size = file.size
    
    if file_size < MIN_FILE_SIZE:
        raise ValidationError(
            f"File size is too small. Minimum: {MIN_FILE_SIZE / 1024:.0f} KB"
        )
    
    if file_size > MAX_FILE_SIZE:
        raise ValidationError(
            f"File size is too large. Maximum: {MAX_FILE_SIZE / (1024 * 1024):.0f} MB"
        )


def validate_image_dimensions(
    file: InMemoryUploadedFile | TemporaryUploadedFile,
    photo_type: Optional[str] = None
) -> None:
    """
    Validate image dimensions and aspect ratio.
    
    Args:
        file: The uploaded file object
        photo_type: Optional photo type for specific validation
        
    Raises:
        ValidationError: If dimensions are not within limits
    """
    try:
        file.seek(0)
        image = Image.open(file)
        width, height = image.size
        file.seek(0)
    except Exception as e:
        raise ValidationError(f"Could not read image dimensions: {str(e)}")
    
    # Check minimum dimensions
    if width < MIN_WIDTH or height < MIN_HEIGHT:
        raise ValidationError(
            f"Image dimensions too small. Minimum: {MIN_WIDTH}x{MIN_HEIGHT}px, "
            f"got: {width}x{height}px"
        )
    
    # Check maximum dimensions
    if width > MAX_WIDTH or height > MAX_HEIGHT:
        raise ValidationError(
            f"Image dimensions too large. Maximum: {MAX_WIDTH}x{MAX_HEIGHT}px, "
            f"got: {width}x{height}px"
        )
    
    # Check aspect ratio for specific photo types
    if photo_type and photo_type in ASPECT_RATIO_LIMITS:
        aspect_ratio = width / height
        limits = ASPECT_RATIO_LIMITS[photo_type]
        
        if aspect_ratio < limits['min'] or aspect_ratio > limits['max']:
            raise ValidationError(
                f"Invalid aspect ratio for {photo_type}. "
                f"Expected ratio between {limits['min']:.2f} and {limits['max']:.2f}, "
                f"got: {aspect_ratio:.2f}"
            )


def validate_image(
    file: InMemoryUploadedFile | TemporaryUploadedFile,
    photo_type: Optional[str] = None
) -> None:
    """
    Run all image validations.
    
    Args:
        file: The uploaded file object
        photo_type: Optional photo type for specific validation
        
    Raises:
        ValidationError: If any validation fails
    """
    validate_image_file_type(file)
    validate_image_file_size(file)
    validate_image_dimensions(file, photo_type)


def validate_image_content_safety(file: InMemoryUploadedFile | TemporaryUploadedFile) -> None:
    """
    Placeholder for content safety validation.
    
    This could integrate with services like:
    - AWS Rekognition
    - Google Cloud Vision
    - Azure Content Moderator
    
    For now, this is a no-op but provides extension point.
    
    Args:
        file: The uploaded file object
        
    Raises:
        ValidationError: If content is deemed unsafe
    """
    # TODO: Integrate with content moderation API
    pass
