use anyhow::{Result, Context};
use tracing::{info, warn, error};
use uuid::Uuid;
use tokio::process::Command;
use std::path::Path;

/// Intel Arc A770 hardware-accelerated thumbnail generation
pub struct ThumbnailGenerator;

impl ThumbnailGenerator {
    /// Generate thumbnail using Intel Arc A770 QSV hardware acceleration
    pub async fn generate_thumbnail(
        source_path: &str,
        media_id: Uuid,
        thumbnail_dir: &str,
    ) -> Result<String> {
        info!("📸 Intel Arc A770 thumbnail generation for {}", media_id);
        
        // Create thumbnails directory if it doesn't exist
        tokio::fs::create_dir_all(thumbnail_dir).await
            .context("Failed to create thumbnail directory")?;
        
        let thumbnail_path = format!("{}/{}.jpg", thumbnail_dir, media_id);
        
        // Check if thumbnail already exists
        if Path::new(&thumbnail_path).exists() {
            info!("📦 Thumbnail already exists for {}", media_id);
            return Ok(thumbnail_path);
        }
        
        info!("🚀 Generating thumbnail with Arc A770: {} → {}", source_path, thumbnail_path);
        
        let start_time = std::time::Instant::now();
        
        // Extract thumbnail at 5% of video duration for better representative frame
        let output = Command::new("ffmpeg")
            .args(&[
                "-hwaccel", "qsv",                        // Intel Quick Sync hardware acceleration
                "-hwaccel_device", "/dev/dri/renderD128", // Intel Arc A770
                "-ss", "00:02:00",                        // Seek to 2 minutes (good representative frame)
                "-i", source_path,                        // Input video
                "-vf", "scale_qsv=320:180:format=nv12",   // QSV hardware scaling with format conversion
                "-c:v", "mjpeg_qsv",                      // QSV hardware MJPEG encoder
                "-vframes", "1",                          // Extract single frame
                "-q:v", "2",                              // High quality JPEG
                "-f", "image2",                           // Image format
                "-y",                                     // Overwrite existing
                &thumbnail_path
            ])
            .output()
            .await
            .context("Failed to run Arc A770 thumbnail extraction")?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            error!("❌ Arc A770 thumbnail generation failed: {}", stderr);
            return Err(anyhow::anyhow!("Arc A770 thumbnail generation failed: {}", stderr));
        }
        
        let generation_time = start_time.elapsed();
        
        // Verify thumbnail was created and get size
        let thumbnail_size = tokio::fs::metadata(&thumbnail_path).await
            .map(|m| m.len())
            .unwrap_or(0);
        
        info!("✅ Arc A770 thumbnail generated: {:.2}s, {} bytes → {}", 
              generation_time.as_secs_f64(), thumbnail_size, thumbnail_path);
        
        info!("📊 METRICS: ARC_A770_THUMBNAIL_SUCCESS media_id={} duration_ms={} size_bytes={}", 
              media_id, generation_time.as_millis(), thumbnail_size);
        
        Ok(thumbnail_path)
    }
    
    /// Scan for videos missing thumbnails and generate them
    pub async fn scan_and_generate_missing_thumbnails(
        media_directory: &str,
        thumbnail_directory: &str,
    ) -> Result<()> {
        info!("🔍 Scanning for videos missing thumbnails in {}", media_directory);
        
        let mut media_dir = tokio::fs::read_dir(media_directory).await
            .context("Failed to read media directory")?;
        
        let mut processed = 0;
        let mut errors = 0;
        
        while let Some(entry) = media_dir.next_entry().await
            .context("Failed to read directory entry")? {
            
            let path = entry.path();
            
            // Check if it's a video file (AV1/MP4)
            if let Some(extension) = path.extension() {
                let ext = extension.to_string_lossy().to_lowercase();
                if ext == "mp4" || ext == "mkv" || ext == "webm" {
                    if let Some(file_stem) = path.file_stem() {
                        let file_name = file_stem.to_string_lossy();
                        
                        // Try to parse as UUID (our media naming convention)
                        if let Ok(media_id) = Uuid::parse_str(&file_name) {
                            match Self::generate_thumbnail(
                                path.to_str().unwrap(),
                                media_id,
                                thumbnail_directory,
                            ).await {
                                Ok(_) => {
                                    processed += 1;
                                    info!("📸 Processed thumbnail for {}", media_id);
                                }
                                Err(e) => {
                                    errors += 1;
                                    warn!("❌ Failed to generate thumbnail for {}: {}", media_id, e);
                                }
                            }
                        }
                    }
                }
            }
        }
        
        info!("📊 Thumbnail scan complete: {} processed, {} errors", processed, errors);
        
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_thumbnail_generation() {
        // Test with a sample video file
        let media_id = Uuid::new_v4();
        let result = ThumbnailGenerator::generate_thumbnail(
            "/path/to/test/video.mp4",
            media_id,
            "/tmp/test_thumbnails"
        ).await;
        
        match result {
            Ok(path) => println!("✅ Thumbnail generated: {}", path),
            Err(e) => println!("❌ Thumbnail generation failed: {}", e),
        }
    }
}