#!/usr/bin/env python3
"""
Video downloader service for visualization.

Downloads MP4 video (720p) alongside audio for the video player.
Integrates with existing yt-dlp download infrastructure.
"""

import logging
import time
from pathlib import Path
from typing import Optional

import yt_dlp

logger = logging.getLogger("VisualizerBackend.VideoDownloader")


def download_video(url: str, output_dir: Path, max_retries: int = 3) -> Optional[Path]:
    """
    Download video for visualization (720p MP4).
    
    Strategy:
    - Download best video up to 720p resolution
    - Merge with audio for complete playback
    - Output as MP4 for browser compatibility
    - Cache and reuse if already downloaded
    
    Args:
        url: YouTube URL
        output_dir: Directory to save video (should be video_id directory)
        max_retries: Number of download retries (default: 3)
    
    Returns:
        Path to downloaded MP4 file, or None if download fails
    """
    logger.info(f"🎥 Downloading video for visualization: {url}")
    start = time.time()
    
    # Determine video ID from output directory name
    video_id = output_dir.name
    output_file = output_dir / f"{video_id}.mp4"
    
    # Check cache
    if output_file.exists():
        file_size = output_file.stat().st_size
        if file_size > 1_000_000:  # At least 1MB
            logger.info(f"✅ Using cached video: {output_file}")
            return output_file
        else:
            logger.warning(f"⚠️ Cached video too small ({file_size} bytes), re-downloading")
            output_file.unlink()
    
    # Ensure output directory exists
    output_dir.mkdir(parents=True, exist_ok=True)
    
    # yt-dlp options for video download
    ydl_opts = {
        # Format: best video up to 720p + best audio, merge to MP4
        'format': 'bestvideo[height<=720][ext=mp4]+bestaudio[ext=m4a]/bestvideo[height<=720]+bestaudio/best[height<=720]',
        'outtmpl': str(output_dir / f"{video_id}.%(ext)s"),
        'merge_output_format': 'mp4',
        'quiet': True,
        'no_warnings': True,
        
        # Quality settings
        'postprocessors': [{
            'key': 'FFmpegVideoConvertor',
            'preferedformat': 'mp4',
        }],
        
        # Network settings
        'retries': 3,
        'fragment_retries': 3,
        'http_chunk_size': 10485760,  # 10MB chunks
        
        # Speed up download
        'concurrent_fragment_downloads': 4,
    }
    
    # Retry loop for transient failures
    last_error = None
    for attempt in range(max_retries):
        try:
            logger.info(f"   Video download attempt {attempt + 1}/{max_retries}")
            
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info = ydl.extract_info(url, download=True)
                
                if info:
                    title = info.get('title', 'Unknown')
                    duration = info.get('duration', 0)
                    logger.info(f"   Video info: '{title}' ({duration}s)")
            
            # Verify download succeeded
            if output_file.exists():
                file_size = output_file.stat().st_size
                
                if file_size < 100_000:  # Less than 100KB is suspicious
                    raise Exception(f"Downloaded file too small: {file_size} bytes")
                
                elapsed = time.time() - start
                logger.info(f"✅ Video download complete: {output_file} ({file_size / 1e6:.1f}MB in {elapsed:.1f}s)")
                return output_file
            else:
                # Try to find file with any extension and rename
                for video_file in output_dir.glob(f"{video_id}.*"):
                    if video_file.suffix in ['.mp4', '.mkv', '.webm']:
                        if video_file.suffix != '.mp4':
                            # Convert to MP4 if needed
                            logger.info(f"   Converting {video_file.suffix} to MP4...")
                            import subprocess
                            subprocess.run([
                                'ffmpeg', '-i', str(video_file),
                                '-c:v', 'copy', '-c:a', 'copy',
                                str(output_file), '-y'
                            ], capture_output=True, check=True)
                            video_file.unlink()
                        else:
                            video_file.rename(output_file)
                        
                        if output_file.exists():
                            elapsed = time.time() - start
                            logger.info(f"✅ Video download complete: {output_file} ({elapsed:.1f}s)")
                            return output_file
                
                raise Exception(f"Downloaded file not found: {output_file}")
        
        except Exception as e:
            last_error = e
            logger.warning(f"   Video download attempt {attempt + 1} failed: {e}")
            
            if attempt < max_retries - 1:
                wait_time = 2 ** attempt  # Exponential backoff
                logger.info(f"   Retrying in {wait_time}s...")
                time.sleep(wait_time)
            continue
    
    # All retries failed
    logger.error(f"❌ Video download failed after {max_retries} attempts: {last_error}")
    return None


def download_thumbnail(url: str, output_dir: Path) -> Optional[Path]:
    """
    Download video thumbnail for preview.
    
    Args:
        url: YouTube URL
        output_dir: Directory to save thumbnail
        
    Returns:
        Path to thumbnail file, or None if download fails
    """
    logger.info(f"🖼️ Downloading thumbnail: {url}")
    
    video_id = output_dir.name
    thumbnail_file = output_dir / "thumbnail.jpg"
    
    # Check cache
    if thumbnail_file.exists():
        logger.info(f"✅ Using cached thumbnail: {thumbnail_file}")
        return thumbnail_file
    
    output_dir.mkdir(parents=True, exist_ok=True)
    
    ydl_opts = {
        'writethumbnail': True,
        'skip_download': True,
        'outtmpl': str(output_dir / video_id),
        'quiet': True,
        'no_warnings': True,
    }
    
    try:
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            ydl.extract_info(url, download=True)
        
        # Find downloaded thumbnail
        for thumb in output_dir.glob(f"{video_id}.*"):
            if thumb.suffix in ['.jpg', '.jpeg', '.png', '.webp']:
                if thumb != thumbnail_file:
                    thumb.rename(thumbnail_file)
                return thumbnail_file
        
        logger.warning(f"⚠️ Thumbnail not found after download")
        return None
        
    except Exception as e:
        logger.error(f"❌ Thumbnail download failed: {e}")
        return None

