//! Video processing functionality

pub mod upscale;
pub mod interpolation;
pub mod converter;

use std::path::Path;
use serde::{Deserialize, Serialize};

use crate::core::{TvaiError, ProcessResult, TvaiProcessor, ProgressCallback};
use crate::config::{UpscaleModel, InterpolationModel, QualityPreset};

/// 音频处理模式
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AudioMode {
    /// 保留原音频
    Keep,
    /// 移除音频
    Remove,
    /// 重新编码音频
    Reencode { codec: String, bitrate: u32 },
}

/// Parameters for video upscaling
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoUpscaleParams {
    // 基础参数
    pub scale_factor: f32,
    pub model: UpscaleModel,
    pub compression: f32,
    pub blend: f32,
    pub quality_preset: QualityPreset,

    // 高级TVAI参数
    pub preblur: f32,        // 预模糊 (0-100)
    pub noise: f32,          // 噪点减少 (0-100)
    pub details: f32,        // 细节恢复 (0-100)
    pub halo: f32,           // 光晕减少 (0-100)
    pub blur: f32,           // 模糊减少 (0-100)
    pub estimate: u32,       // 估算质量 (1-20)
    pub device: i32,         // 设备ID (-2=auto, -1=CPU, 0+=GPU)
    pub vram: u32,           // VRAM使用 (0-1)
    pub instances: u32,      // 实例数量 (1-4)

    // 输出尺寸控制
    pub target_width: Option<u32>,   // 目标宽度
    pub target_height: Option<u32>,  // 目标高度
    pub maintain_aspect: bool,       // 保持宽高比
    pub pad_color: String,           // 填充颜色

    // 编码参数
    pub codec: Option<String>,       // 编码器 (h264_nvenc, hevc_nvenc, libx264等)
    pub profile: Option<String>,     // 编码配置文件
    pub pixel_format: String,        // 像素格式
    pub gop_size: u32,              // GOP大小
    pub preset: Option<String>,      // 编码预设
    pub tune: Option<String>,        // 调优选项
    pub rate_control: String,        // 码率控制模式
    pub quality_param: u32,          // 质量参数 (CRF/QP)
    pub lookahead: u32,             // 前瞻帧数
    pub spatial_aq: bool,           // 空间自适应量化
    pub aq_strength: u32,           // AQ强度
    pub bitrate: u32,               // 目标码率 (0=VBR)
    pub buffer_frames: u32,         // 缓冲帧数

    // 音频处理
    pub audio_mode: AudioMode,       // 音频处理模式

    // 元数据
    pub preserve_metadata: bool,     // 保留元数据
    pub custom_metadata: Option<String>, // 自定义元数据
}

/// Parameters for frame interpolation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InterpolationParams {
    pub input_fps: u32,
    pub multiplier: f32,
    pub model: InterpolationModel,
    pub target_fps: Option<u32>,
}

/// Combined parameters for video enhancement
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoEnhanceParams {
    pub upscale: Option<VideoUpscaleParams>,
    pub interpolation: Option<InterpolationParams>,
}

impl Default for VideoUpscaleParams {
    fn default() -> Self {
        Self {
            // 基础参数
            scale_factor: 2.0,
            model: UpscaleModel::Iris3,
            compression: 0.0,
            blend: 0.0,
            quality_preset: QualityPreset::HighQuality,

            // 高级TVAI参数
            preblur: 0.0,
            noise: 0.0,
            details: 0.0,
            halo: 0.0,
            blur: 0.0,
            estimate: 8,
            device: -2, // 自动选择
            vram: 1,
            instances: 1,

            // 输出尺寸控制
            target_width: None,
            target_height: None,
            maintain_aspect: true,
            pad_color: "black".to_string(),

            // 编码参数
            codec: None, // 自动选择
            profile: Some("high".to_string()),
            pixel_format: "yuv420p".to_string(),
            gop_size: 30,
            preset: Some("p7".to_string()),
            tune: Some("hq".to_string()),
            rate_control: "constqp".to_string(),
            quality_param: 18,
            lookahead: 20,
            spatial_aq: true,
            aq_strength: 15,
            bitrate: 0, // VBR
            buffer_frames: 0,

            // 音频处理
            audio_mode: AudioMode::Keep,

            // 元数据
            preserve_metadata: true,
            custom_metadata: None,
        }
    }
}

impl VideoUpscaleParams {
    /// Create parameters optimized for old video content
    pub fn for_old_video() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Thf4,
            compression: 0.3,
            blend: 0.2,
            preblur: 0.0,
            noise: 20.0,
            details: 30.0,
            halo: 10.0,
            blur: 15.0,
            ..Default::default()
        }
    }
    
    /// Create parameters optimized for game content
    pub fn for_game_content() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Ghq5,
            compression: 0.0,
            blend: 0.0,
            preblur: 0.0,
            noise: 0.0,
            details: 50.0,
            halo: 0.0,
            blur: 0.0,
            quality_param: 15, // 更高质量
            ..Default::default()
        }
    }

    /// Create parameters optimized for animation
    pub fn for_animation() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Iris3,
            compression: -0.1,
            blend: 0.1,
            preblur: 0.0,
            noise: 5.0,
            details: 25.0,
            halo: 5.0,
            blur: 10.0,
            ..Default::default()
        }
    }

    /// Create parameters optimized for portrait video
    pub fn for_portrait() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Nyx3,
            compression: -0.2,
            blend: 0.1,
            preblur: 0.0,
            noise: 15.0,
            details: 40.0,
            halo: 20.0,
            blur: 25.0,
            ..Default::default()
        }
    }

    /// Create parameters for maximum quality (slow processing)
    pub fn for_maximum_quality() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Ahq12,
            compression: 0.0,
            blend: 0.0,
            preblur: 0.0,
            noise: 30.0,
            details: 60.0,
            halo: 30.0,
            blur: 40.0,
            estimate: 20, // 最高估算质量
            quality_param: 12, // 最高质量
            lookahead: 32,
            instances: 1, // 单实例确保质量
            ..Default::default()
        }
    }

    /// Create parameters for fast processing
    pub fn for_fast_processing() -> Self {
        Self {
            scale_factor: 2.0,
            model: UpscaleModel::Alqs2,
            compression: 0.2,
            blend: 0.0,
            preblur: 0.0,
            noise: 10.0,
            details: 20.0,
            halo: 5.0,
            blur: 10.0,
            estimate: 4, // 较低估算质量
            quality_param: 22, // 较低质量但更快
            preset: Some("p1".to_string()), // 最快预设
            instances: 2, // 多实例加速
            ..Default::default()
        }
    }
}

impl InterpolationParams {
    /// Create parameters for smooth slow motion
    pub fn for_slow_motion(input_fps: u32, multiplier: f32) -> Self {
        Self {
            input_fps,
            multiplier,
            model: InterpolationModel::Apo8,
            target_fps: None,
        }
    }
    
    /// Create parameters for animation interpolation
    pub fn for_animation(input_fps: u32, multiplier: f32) -> Self {
        Self {
            input_fps,
            multiplier,
            model: InterpolationModel::Chr2,
            target_fps: None,
        }
    }
}

/// Enhanced video processing with both upscaling and interpolation
impl TvaiProcessor {
    /// Enhance video with combined upscaling and interpolation
    pub async fn enhance_video(
        &mut self,
        input_path: &Path,
        output_path: &Path,
        params: VideoEnhanceParams,
        progress_callback: Option<&ProgressCallback>,
    ) -> Result<ProcessResult, TvaiError> {
        let start_time = std::time::Instant::now();

        // Validate inputs
        self.validate_input_file(input_path)?;
        self.validate_output_path(output_path)?;

        let operation_id = self.generate_operation_id();
        let mut current_input = input_path.to_path_buf();
        let mut intermediate_files = Vec::new();

        if let Some(callback) = progress_callback {
            callback(0.0);
        }

        // Step 1: Apply upscaling if requested
        if let Some(upscale_params) = &params.upscale {
            let intermediate_output = self.create_temp_path(&operation_id, "upscaled.mp4");
            intermediate_files.push(intermediate_output.clone());

            // For now, pass None for progress callback to avoid lifetime issues
            // TODO: Implement proper progress callback forwarding
            self.upscale_video(
                &current_input,
                &intermediate_output,
                upscale_params.clone(),
                None,
            ).await?;

            if let Some(callback) = progress_callback {
                callback(0.5);
            }

            current_input = intermediate_output;
        }

        if let Some(callback) = progress_callback {
            callback(0.5);
        }

        // Step 2: Apply interpolation if requested
        if let Some(interpolation_params) = &params.interpolation {
            // For now, pass None for progress callback to avoid lifetime issues
            // TODO: Implement proper progress callback forwarding
            let result = self.interpolate_video(
                &current_input,
                output_path,
                interpolation_params.clone(),
                None,
            ).await?;

            // Clean up intermediate files
            self.cleanup_temp_files(&operation_id)?;

            return Ok(result);
        }

        // If only upscaling was requested, move the result to final output
        if params.upscale.is_some() && params.interpolation.is_none() {
            std::fs::rename(&current_input, output_path)?;
        } else {
            return Err(TvaiError::InvalidParameter(
                "At least one enhancement (upscale or interpolation) must be specified".to_string()
            ));
        }

        let processing_time = start_time.elapsed();

        // Create combined metadata
        let mut metadata = self.create_metadata(
            operation_id,
            input_path,
            format!("enhance: upscale={}, interpolation={}",
                params.upscale.is_some(),
                params.interpolation.is_some()
            ),
        );
        metadata.ffmpeg_version = self.get_ffmpeg_version(true).await.ok();

        if let Some(callback) = progress_callback {
            callback(1.0);
        }

        Ok(ProcessResult {
            output_path: output_path.to_path_buf(),
            processing_time,
            metadata,
        })
    }
}

/// Quick video upscaling function
pub async fn quick_upscale_video(
    input: &Path,
    output: &Path,
    scale: f32,
) -> Result<ProcessResult, TvaiError> {
    quick_upscale_video_with_model(input, output, scale, None).await
}

/// Quick video upscaling function with model selection
pub async fn quick_upscale_video_with_model(
    input: &Path,
    output: &Path,
    scale: f32,
    model: Option<UpscaleModel>,
) -> Result<ProcessResult, TvaiError> {
    // Detect Topaz installation
    let topaz_path = crate::utils::detect_topaz_installation()
        .ok_or_else(|| TvaiError::TopazNotFound("Topaz Video AI not found".to_string()))?;

    // Create default configuration
    let config = crate::core::TvaiConfig::builder()
        .topaz_path(topaz_path)
        .use_gpu(true)
        .build()?;

    // Create processor
    let mut processor = TvaiProcessor::new(config)?;

    // Create upscaling parameters with specified or default model
    let params = VideoUpscaleParams {
        scale_factor: scale,
        model: model.unwrap_or(crate::config::UpscaleModel::Iris3), // Use specified model or default to Iris3
        compression: 0.0,
        blend: 0.0,
        quality_preset: crate::config::QualityPreset::HighQuality,
        ..Default::default()
    };

    // Perform upscaling
    processor.upscale_video(input, output, params, None).await
}

/// Automatic video enhancement
pub async fn auto_enhance_video(
    input: &Path,
    output: &Path,
) -> Result<ProcessResult, TvaiError> {
    // Detect Topaz installation
    let topaz_path = crate::utils::detect_topaz_installation()
        .ok_or_else(|| TvaiError::TopazNotFound("Topaz Video AI not found".to_string()))?;

    // Create default configuration
    let config = crate::core::TvaiConfig::builder()
        .topaz_path(topaz_path)
        .use_gpu(true)
        .build()?;

    // Create processor
    let mut processor = TvaiProcessor::new(config)?;

    // Get video info to determine best enhancement strategy
    let video_info = crate::utils::get_video_info(input).await?;

    // Auto-determine enhancement parameters based on video characteristics
    let mut enhance_params = VideoEnhanceParams {
        upscale: None,
        interpolation: None,
    };

    // Apply upscaling if resolution is low
    if video_info.width < 1920 || video_info.height < 1080 {
        let scale_factor = if video_info.width <= 720 { 2.0 } else { 1.5 };
        enhance_params.upscale = Some(VideoUpscaleParams {
            scale_factor,
            model: crate::config::UpscaleModel::Iris3,
            compression: 0.0,
            blend: 0.1,
            quality_preset: crate::config::QualityPreset::HighQuality,
            ..Default::default()
        });
    }

    // Apply interpolation if frame rate is low
    if video_info.fps < 30.0 {
        let multiplier = if video_info.fps <= 15.0 { 2.0 } else { 1.5 };
        enhance_params.interpolation = Some(InterpolationParams {
            input_fps: video_info.fps as u32,
            multiplier,
            model: crate::config::InterpolationModel::Apo8,
            target_fps: None,
        });
    }

    // If no enhancement is needed, just copy the file
    if enhance_params.upscale.is_none() && enhance_params.interpolation.is_none() {
        std::fs::copy(input, output)?;
        return Ok(ProcessResult {
            output_path: output.to_path_buf(),
            processing_time: std::time::Duration::from_millis(0),
            metadata: processor.create_metadata(
                processor.generate_operation_id(),
                input,
                "auto_enhance: no enhancement needed".to_string(),
            ),
        });
    }

    // Perform enhancement
    processor.enhance_video(input, output, enhance_params, None).await
}

/// Quick video interpolation function
pub async fn quick_interpolate_video(
    input: &Path,
    output: &Path,
    multiplier: f32,
    input_fps: u32,
) -> Result<ProcessResult, TvaiError> {
    // Detect Topaz installation
    let topaz_path = crate::utils::detect_topaz_installation()
        .ok_or_else(|| TvaiError::TopazNotFound("Topaz Video AI not found".to_string()))?;

    // Create default configuration
    let config = crate::core::TvaiConfig::builder()
        .topaz_path(topaz_path)
        .use_gpu(true)
        .build()?;

    // Create processor
    let mut processor = TvaiProcessor::new(config)?;

    // Create default interpolation parameters
    let params = InterpolationParams {
        input_fps,
        multiplier,
        model: crate::config::InterpolationModel::Apo8, // Best general purpose interpolation model
        target_fps: None, // Auto-calculate based on multiplier
    };

    // Perform interpolation
    processor.interpolate_video(input, output, params, None).await
}

/// Process video using a Topaz template
pub async fn process_with_template(
    input: &Path,
    output: &Path,
    template_name: &str,
) -> Result<ProcessResult, TvaiError> {
    // Get template manager
    let manager = crate::config::global_topaz_templates().lock()
        .map_err(|_| TvaiError::ConfigurationError("Failed to access template manager".to_string()))?;

    // Apply template
    let applied = manager.apply_template(template_name)?;
    drop(manager); // Release lock early

    // Detect Topaz installation
    let topaz_path = crate::utils::detect_topaz_installation()
        .ok_or_else(|| TvaiError::TopazNotFound("Topaz Video AI not found".to_string()))?;

    // Create default configuration
    let config = crate::core::TvaiConfig::builder()
        .topaz_path(topaz_path)
        .use_gpu(true)
        .build()?;

    // Create processor
    let mut processor = TvaiProcessor::new(config)?;

    // Process video with template parameters
    processor.enhance_video(input, output, applied.enhance_params, None).await
}

/// List all available templates
pub fn list_available_templates() -> Vec<String> {
    let manager = crate::config::global_topaz_templates().lock()
        .unwrap_or_else(|_| panic!("Failed to access template manager"));
    manager.list_templates()
}

/// Get template information
pub fn get_template_info(template_name: &str) -> Option<(String, String)> {
    let manager = crate::config::global_topaz_templates().lock()
        .unwrap_or_else(|_| panic!("Failed to access template manager"));

    manager.get_template(template_name)
        .map(|template| (template.name.clone(), template.description.clone()))
}

/// Quick functions for common templates
pub async fn upscale_to_4k(input: &Path, output: &Path) -> Result<ProcessResult, TvaiError> {
    process_with_template(input, output, "upscale_to_4k").await
}

pub async fn convert_to_60fps(input: &Path, output: &Path) -> Result<ProcessResult, TvaiError> {
    process_with_template(input, output, "convert_to_60fps").await
}

pub async fn remove_noise(input: &Path, output: &Path) -> Result<ProcessResult, TvaiError> {
    process_with_template(input, output, "remove_noise").await
}

pub async fn slow_motion_4x(input: &Path, output: &Path) -> Result<ProcessResult, TvaiError> {
    process_with_template(input, output, "4x_slow_motion").await
}

pub async fn auto_crop_stabilization(input: &Path, output: &Path) -> Result<ProcessResult, TvaiError> {
    process_with_template(input, output, "auto_crop_stabilization").await
}
