use tauri::command;
use std::sync::{Arc, Mutex};
use tracing::{info, error, warn, debug};
use lazy_static::lazy_static;
use base64::{Engine as _, engine::general_purpose};

use crate::infrastructure::frame_extractor::{
    FrameExtractorService, FrameExtractionConfig, VideoFileInfo, 
    FrameExtractionResult, FrameType, TimePoint, ImageFormat, 
    ImageQuality, OutputSize
};

lazy_static! {
    static ref FRAME_EXTRACTOR_INITIALIZED: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
}

/// 初始化关键帧提取服务
async fn ensure_initialized() -> Result<(), String> {
    let needs_init = {
        let initialized = FRAME_EXTRACTOR_INITIALIZED.lock().unwrap();
        !*initialized
    };

    if needs_init {
        match FrameExtractorService::initialize().await {
            Ok(_) => {
                let mut initialized = FRAME_EXTRACTOR_INITIALIZED.lock().unwrap();
                *initialized = true;
                info!("关键帧提取服务初始化成功");
                Ok(())
            }
            Err(e) => {
                error!("关键帧提取服务初始化失败: {}", e);
                Err(format!("初始化失败: {}", e))
            }
        }
    } else {
        Ok(())
    }
}

/// 文件夹扫描请求
#[derive(Debug, serde::Deserialize)]
pub struct FolderScanRequest {
    pub folder_path: String,
    pub recursive: bool,
    pub supported_formats: Vec<String>,
}

/// 帧提取请求
#[derive(Debug, serde::Deserialize)]
pub struct FrameExtractionRequest {
    pub video_files: Vec<String>,
    pub config: FrameExtractionConfig,
}

/// 帧预览请求
#[derive(Debug, serde::Deserialize)]
pub struct FramePreviewRequest {
    pub video_path: String,
    pub timestamp: f64,
    pub output_size: Option<OutputSize>,
}

/// 帧预览结果
#[derive(Debug, serde::Serialize)]
pub struct FramePreviewResult {
    pub success: bool,
    pub preview_data: Option<String>, // Base64 encoded image
    pub error_message: Option<String>,
    pub timestamp: f64,
    pub original_size: (u32, u32),
    pub preview_size: (u32, u32),
}

/// 检查 FFmpeg 是否可用
#[command]
pub async fn check_ffmpeg_availability() -> Result<bool, String> {
    ensure_initialized().await?;
    Ok(FrameExtractorService::is_available())
}

/// 获取视频文件信息
#[command]
pub async fn get_video_info(video_path: String) -> Result<VideoFileInfo, String> {
    ensure_initialized().await?;
    
    debug!("获取视频信息: {}", video_path);
    
    match FrameExtractorService::get_video_info(&video_path).await {
        Ok(info) => {
            debug!("视频信息获取成功: {:?}", info);
            Ok(info)
        }
        Err(e) => {
            error!("获取视频信息失败 {}: {}", video_path, e);
            Err(format!("获取视频信息失败: {}", e))
        }
    }
}

/// 扫描文件夹中的视频文件
#[command]
pub async fn scan_video_files(request: FolderScanRequest) -> Result<Vec<VideoFileInfo>, String> {
    ensure_initialized().await?;
    
    info!("扫描视频文件: {:?}", request);
    
    match FrameExtractorService::scan_video_files(
        &request.folder_path,
        request.recursive,
        &request.supported_formats,
    ).await {
        Ok(files) => {
            info!("扫描完成，找到 {} 个视频文件", files.len());
            Ok(files)
        }
        Err(e) => {
            error!("扫描视频文件失败: {}", e);
            Err(format!("扫描失败: {}", e))
        }
    }
}

/// 提取单个帧
#[command]
pub async fn extract_single_frame(
    video_path: String,
    timestamp: f64,
    output_path: String,
    config: FrameExtractionConfig,
) -> Result<FrameExtractionResult, String> {
    ensure_initialized().await?;
    
    debug!("提取单个帧: video={}, timestamp={}, output={}", video_path, timestamp, output_path);
    
    match FrameExtractorService::extract_frame(&video_path, timestamp, &output_path, &config).await {
        Ok(result) => {
            if result.success {
                info!("帧提取成功: {} -> {}", video_path, output_path);
            } else {
                warn!("帧提取失败: {}", result.error_message.as_deref().unwrap_or("未知错误"));
            }
            Ok(result)
        }
        Err(e) => {
            error!("提取帧失败: {}", e);
            Err(format!("提取失败: {}", e))
        }
    }
}

/// 批量提取帧
#[command]
pub async fn extract_frames_batch(request: FrameExtractionRequest) -> Result<Vec<FrameExtractionResult>, String> {
    ensure_initialized().await?;
    
    info!("开始批量提取帧: {} 个视频文件", request.video_files.len());
    
    // 首先获取所有视频文件信息
    let mut video_infos = Vec::new();
    for video_path in &request.video_files {
        match FrameExtractorService::get_video_info(video_path).await {
            Ok(info) => video_infos.push(info),
            Err(e) => {
                warn!("获取视频信息失败 {}: {}", video_path, e);
                // 创建一个错误的视频信息对象
                video_infos.push(VideoFileInfo {
                    path: video_path.clone(),
                    filename: std::path::Path::new(video_path)
                        .file_name()
                        .unwrap_or_default()
                        .to_string_lossy()
                        .to_string(),
                    size: 0,
                    duration: 0.0,
                    width: 0,
                    height: 0,
                    fps: 0.0,
                    format: String::new(),
                    is_valid: false,
                    error_message: Some(e.to_string()),
                });
            }
        }
    }
    
    // 执行批量提取
    match FrameExtractorService::extract_frames_batch(&video_infos, &request.config).await {
        Ok(results) => {
            let success_count = results.iter().filter(|r| r.success).count();
            info!("批量提取完成: {}/{} 成功", success_count, results.len());
            Ok(results)
        }
        Err(e) => {
            error!("批量提取失败: {}", e);
            Err(format!("批量提取失败: {}", e))
        }
    }
}

/// 计算提取时间戳
#[command]
pub async fn calculate_extraction_timestamps(
    video_path: String,
    config: FrameExtractionConfig,
) -> Result<Vec<f64>, String> {
    ensure_initialized().await?;
    
    // 获取视频信息
    let video_info = match FrameExtractorService::get_video_info(&video_path).await {
        Ok(info) => info,
        Err(e) => return Err(format!("获取视频信息失败: {}", e)),
    };
    
    // 计算时间戳
    match FrameExtractorService::calculate_extraction_timestamps(&video_info, &config) {
        Ok(timestamps) => {
            debug!("计算时间戳成功: {:?}", timestamps);
            Ok(timestamps)
        }
        Err(e) => {
            error!("计算时间戳失败: {}", e);
            Err(format!("计算时间戳失败: {}", e))
        }
    }
}

/// 生成输出文件路径
#[command]
pub async fn generate_output_path(
    video_path: String,
    config: FrameExtractionConfig,
    timestamp: f64,
    index: Option<usize>,
) -> Result<String, String> {
    // 获取视频信息
    let video_info = match FrameExtractorService::get_video_info(&video_path).await {
        Ok(info) => info,
        Err(e) => return Err(format!("获取视频信息失败: {}", e)),
    };
    
    // 生成输出路径
    match FrameExtractorService::generate_output_path(&video_info, &config, timestamp, index) {
        Ok(path) => {
            debug!("生成输出路径: {}", path);
            Ok(path)
        }
        Err(e) => {
            error!("生成输出路径失败: {}", e);
            Err(format!("生成输出路径失败: {}", e))
        }
    }
}

/// 预览帧（返回 Base64 编码的图片数据）
#[command]
pub async fn preview_frame(request: FramePreviewRequest) -> Result<FramePreviewResult, String> {
    ensure_initialized().await?;
    
    debug!("预览帧: video={}, timestamp={}", request.video_path, request.timestamp);
    
    // 获取视频信息
    let video_info = match FrameExtractorService::get_video_info(&request.video_path).await {
        Ok(info) => info,
        Err(e) => {
            return Ok(FramePreviewResult {
                success: false,
                preview_data: None,
                error_message: Some(format!("获取视频信息失败: {}", e)),
                timestamp: request.timestamp,
                original_size: (0, 0),
                preview_size: (0, 0),
            });
        }
    };
    
    // 创建临时预览配置
    let preview_config = FrameExtractionConfig {
        frame_type: FrameType::Custom,
        time_points: None,
        custom_time: Some(request.timestamp),
        output_format: ImageQuality {
            format: ImageFormat::Jpg,
            quality: 85,
            compression_level: None,
        },
        output_size: request.output_size.clone(),
        output_directory: std::env::temp_dir().to_string_lossy().to_string(),
        filename_pattern: format!("preview_{}", uuid::Uuid::new_v4().to_string()),
        overwrite_existing: true,
    };
    
    // 生成临时输出路径
    let temp_path = match FrameExtractorService::generate_output_path(
        &video_info,
        &preview_config,
        request.timestamp,
        None,
    ) {
        Ok(path) => path,
        Err(e) => {
            return Ok(FramePreviewResult {
                success: false,
                preview_data: None,
                error_message: Some(format!("生成临时路径失败: {}", e)),
                timestamp: request.timestamp,
                original_size: (video_info.width, video_info.height),
                preview_size: (0, 0),
            });
        }
    };
    
    // 提取预览帧
    match FrameExtractorService::extract_frame(
        &request.video_path,
        request.timestamp,
        &temp_path,
        &preview_config,
    ).await {
        Ok(result) => {
            if result.success {
                // 读取文件并转换为 Base64
                match std::fs::read(&temp_path) {
                    Ok(data) => {
                        let base64_data = general_purpose::STANDARD.encode(&data);
                        
                        // 清理临时文件
                        let _ = std::fs::remove_file(&temp_path);
                        
                        // 计算预览尺寸
                        let preview_size = if let Some(size) = &request.output_size {
                            (
                                size.width.unwrap_or(video_info.width),
                                size.height.unwrap_or(video_info.height),
                            )
                        } else {
                            (video_info.width, video_info.height)
                        };
                        
                        Ok(FramePreviewResult {
                            success: true,
                            preview_data: Some(base64_data),
                            error_message: None,
                            timestamp: request.timestamp,
                            original_size: (video_info.width, video_info.height),
                            preview_size,
                        })
                    }
                    Err(e) => {
                        let _ = std::fs::remove_file(&temp_path);
                        Ok(FramePreviewResult {
                            success: false,
                            preview_data: None,
                            error_message: Some(format!("读取预览文件失败: {}", e)),
                            timestamp: request.timestamp,
                            original_size: (video_info.width, video_info.height),
                            preview_size: (0, 0),
                        })
                    }
                }
            } else {
                Ok(FramePreviewResult {
                    success: false,
                    preview_data: None,
                    error_message: result.error_message,
                    timestamp: request.timestamp,
                    original_size: (video_info.width, video_info.height),
                    preview_size: (0, 0),
                })
            }
        }
        Err(e) => {
            let _ = std::fs::remove_file(&temp_path);
            Ok(FramePreviewResult {
                success: false,
                preview_data: None,
                error_message: Some(format!("提取预览帧失败: {}", e)),
                timestamp: request.timestamp,
                original_size: (video_info.width, video_info.height),
                preview_size: (0, 0),
            })
        }
    }
}
