"""Video thumbnail generation service with caching."""

from __future__ import annotations

import hashlib
import os
from pathlib import Path
from typing import Optional

from PIL import Image


# Cache directory for thumbnails (relative to project root)
# Will be created in the same directory as the database
THUMBNAIL_CACHE_DIR = Path(__file__).parent.parent.parent.parent / "data" / "thumbnails"
THUMBNAIL_SIZE = (320, 240)  # Width, Height
THUMBNAIL_QUALITY = 85  # JPEG quality


def get_thumbnail_cache_path(video_path: str) -> Path:
    """Get cache path for a video thumbnail.
    
    Args:
        video_path: Full path to video file
    
    Returns:
        Path to cached thumbnail file
    """
    # Create hash of video path for cache filename
    path_hash = hashlib.md5(video_path.encode()).hexdigest()
    # Use original filename (without extension) + hash for uniqueness
    video_file = Path(video_path)
    cache_filename = f"{video_file.stem}_{path_hash[:8]}.jpg"
    
    # Ensure cache directory exists
    THUMBNAIL_CACHE_DIR.mkdir(parents=True, exist_ok=True)
    
    return THUMBNAIL_CACHE_DIR / cache_filename


def generate_video_thumbnail(
    video_path: str,
    force_regenerate: bool = False,
) -> Optional[Path]:
    """Generate thumbnail for a video file.
    
    Extracts first frame and creates a cached thumbnail.
    
    Args:
        video_path: Full path to video file
        force_regenerate: If True, regenerate even if cached thumbnail exists
    
    Returns:
        Path to thumbnail file, or None if generation failed
    """
    if not os.path.exists(video_path):
        return None
    
    cache_path = get_thumbnail_cache_path(video_path)
    
    # Return cached thumbnail if it exists and we're not forcing regeneration
    if cache_path.exists() and not force_regenerate:
        return cache_path
    
    try:
        # Try to use OpenCV first (faster, more reliable)
        try:
            import cv2
            
            # Open video file
            cap = cv2.VideoCapture(video_path)
            if not cap.isOpened():
                return None
            
            # Read first frame
            ret, frame = cap.read()
            cap.release()
            
            if not ret or frame is None:
                return None
            
            # Convert BGR to RGB (OpenCV uses BGR)
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            
            # Convert to PIL Image
            image = Image.fromarray(frame_rgb)
            
        except ImportError:
            # Fallback to ffmpeg if OpenCV not available
            import subprocess
            import tempfile
            
            # Extract first frame using ffmpeg
            with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_file:
                tmp_path = tmp_file.name
            
            try:
                # Use ffmpeg to extract first frame
                result = subprocess.run(
                    [
                        "ffmpeg",
                        "-i", video_path,
                        "-vframes", "1",
                        "-q:v", "2",  # High quality
                        "-y",  # Overwrite output
                        tmp_path,
                    ],
                    capture_output=True,
                    timeout=30,  # 30 second timeout
                )
                
                if result.returncode != 0:
                    return None
                
                if not os.path.exists(tmp_path):
                    return None
                
                # Load with PIL
                image = Image.open(tmp_path)
                os.unlink(tmp_path)  # Clean up temp file
                
            except (subprocess.TimeoutExpired, FileNotFoundError, Exception):
                # ffmpeg not available or failed
                if os.path.exists(tmp_path):
                    os.unlink(tmp_path)
                return None
        
        # Resize to thumbnail size (maintain aspect ratio)
        image.thumbnail(THUMBNAIL_SIZE, Image.Resampling.LANCZOS)
        
        # Convert to RGB if needed (for JPEG)
        if image.mode != "RGB":
            image = image.convert("RGB")
        
        # Save to cache
        image.save(cache_path, "JPEG", quality=THUMBNAIL_QUALITY, optimize=True)
        
        return cache_path
        
    except Exception as e:
        # Log error but don't fail
        print(f"⚠️ Failed to generate thumbnail for {video_path}: {e}")
        return None


def get_video_thumbnail_path(video_path: str) -> Optional[Path]:
    """Get thumbnail path for a video, generating if needed.
    
    Args:
        video_path: Full path to video file
    
    Returns:
        Path to thumbnail file, or None if generation failed
    """
    return generate_video_thumbnail(video_path, force_regenerate=False)


def clear_thumbnail_cache() -> int:
    """Clear all cached thumbnails.
    
    Returns:
        Number of files deleted
    """
    if not THUMBNAIL_CACHE_DIR.exists():
        return 0
    
    count = 0
    for file in THUMBNAIL_CACHE_DIR.glob("*.jpg"):
        try:
            file.unlink()
            count += 1
        except Exception:
            pass
    
    return count

