//! Web API for Topaz Video AI Parameter Configurator
//! 
//! This module provides a web API interface for the video processor page.

use crate::config::{TopazTemplate, TopazSettings, FfmpegCommandOptions, RateControlMode, global_topaz_templates};
use serde::{Deserialize, Serialize};

/// Web API request for generating FFmpeg commands
#[derive(Debug, Deserialize)]
pub struct GenerateCommandRequest {
    pub settings: WebTopazSettings,
    pub input_file: String,
    pub output_file: String,
    pub processing_mode: ProcessingMode,
    pub rate_control: String,
}

/// Web API response for generated commands
#[derive(Debug, Serialize)]
pub struct GenerateCommandResponse {
    pub success: bool,
    pub single_command: Option<String>,
    pub analysis_command: Option<String>,
    pub processing_command: Option<String>,
    pub usage_stats: UsageStats,
    pub error: Option<String>,
}

/// Processing mode enum
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProcessingMode {
    Single,
    TwoPass,
}

/// Web-friendly TopazSettings structure
#[derive(Debug, Serialize, Deserialize)]
pub struct WebTopazSettings {
    pub stabilize: WebStabilizeSettings,
    pub motionblur: WebMotionBlurSettings,
    pub slowmo: WebSlowMotionSettings,
    pub enhance: WebEnhanceSettings,
    pub grain: WebGrainSettings,
    pub hdr: WebHdrSettings,
    pub output: WebOutputSettings,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebStabilizeSettings {
    pub active: bool,
    pub smooth: i32,
    pub method: i32,
    pub reduce_motion: i32,
    pub reduce_motion_iteration: i32,
    pub rsc: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebMotionBlurSettings {
    pub active: bool,
    pub model: String,
    pub model_name: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebSlowMotionSettings {
    pub active: bool,
    pub model: String,
    pub factor: i32,
    pub duplicate_threshold: f64,
    pub duplicate: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebEnhanceSettings {
    pub active: bool,
    pub model: String,
    pub video_type: i32,
    pub compress: i32,
    pub detail: i32,
    pub sharpen: i32,
    pub denoise: i32,
    pub dehalo: i32,
    pub deblur: i32,
    pub auto: i32,
    pub recover_original_detail_value: i32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebGrainSettings {
    pub active: bool,
    pub grain: i32,
    pub grain_size: i32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebHdrSettings {
    pub active: bool,
    pub model: String,
    pub auto: i32,
    pub exposure: i32,
    pub saturation: i32,
    pub sdr_inflection_point: f64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebOutputSettings {
    pub active: bool,
    pub out_size_method: i32,
    pub out_fps: i32,
    pub crop_to_fit: bool,
    pub lock_aspect_ratio: bool,
}

/// Usage statistics for the response
#[derive(Debug, Serialize)]
pub struct UsageStats {
    pub enabled_features: Vec<String>,
    pub filter_count: usize,
    pub parameter_usage_rate: f32,
    pub processing_complexity: String,
    pub estimated_processing_time: String,
}

/// Get all available templates
#[derive(Debug, Serialize)]
pub struct TemplateInfo {
    pub key: String,
    pub name: String,
    pub description: String,
    pub settings: TopazSettings,
}

/// Web API implementation
pub struct WebApi;

impl WebApi {
    /// Get all available templates
    pub fn get_templates() -> Result<Vec<TemplateInfo>, String> {
        let manager = global_topaz_templates().lock()
            .map_err(|e| format!("Failed to lock template manager: {}", e))?;

        let mut templates = Vec::new();

        // Get all builtin templates - using complete template names list
        let template_names = [
            "upscale_to_4k",
            "convert_to_60fps",
            "remove_noise",
            "4x_slow_motion",
            "8x_super_slow_motion",
            "auto_crop_stabilization",
            "deinterlace_upscale_fhd",
            "film_stock_4k_light",
            "film_stock_4k_medium",
            "film_stock_4k_strong",
            "minidv_hd_int_basic",
            "upscale_to_fhd",
            "upscale_4k_convert_60fps"
        ];

        for name in &template_names {
            if let Some(template) = manager.get_template(name) {
                templates.push(TemplateInfo {
                    key: name.to_string(),
                    name: template.name.clone(),
                    description: template.description.clone(),
                    settings: template.settings.clone(),
                });
            }
        }

        Ok(templates)
    }
    
    /// Generate FFmpeg command(s) based on web request
    pub fn generate_command(request: GenerateCommandRequest) -> GenerateCommandResponse {
        match Self::generate_command_internal(request) {
            Ok(response) => response,
            Err(error) => GenerateCommandResponse {
                success: false,
                single_command: None,
                analysis_command: None,
                processing_command: None,
                usage_stats: UsageStats {
                    enabled_features: vec![],
                    filter_count: 0,
                    parameter_usage_rate: 0.0,
                    processing_complexity: "Unknown".to_string(),
                    estimated_processing_time: "Unknown".to_string(),
                },
                error: Some(error),
            }
        }
    }
    
    fn generate_command_internal(request: GenerateCommandRequest) -> Result<GenerateCommandResponse, String> {
        let manager = global_topaz_templates().lock()
            .map_err(|e| format!("Failed to lock template manager: {}", e))?;
        
        // Convert web settings to internal format
        let template = Self::web_settings_to_template(&request.settings)?;
        
        // Create FFmpeg options with clean configuration
        let mut options = FfmpegCommandOptions {
            overwrite: true,
            use_gpu: true,
            gpu_type: Some("nvidia".to_string()),
            video_codec: None, // Let the system choose based on GPU
            audio_codec: Some("copy".to_string()),
            crf: None, // Don't use CRF when using QP
            preset: None, // Don't use generic preset when using NVENC preset
            pixel_format: Some("yuv420p".to_string()),
            custom_args: Vec::new(),

            // Topaz defaults
            topaz_device: Some(-2), // Auto-select best GPU
            topaz_vram: Some(1), // Normal VRAM usage
            topaz_instances: Some(1), // Single instance
            blend_ratio: Some(0.2), // 20% blend
            duplicate_threshold: Some(0.01), // 1% threshold

            // Advanced encoding defaults
            nvenc_preset: Some("p7".to_string()), // Highest quality
            use_constqp: true, // Use constant QP like Topaz
            qp_value: Some(18), // High quality
            lookahead: Some(20), // 20 frame lookahead
            spatial_aq: Some(1), // Enable spatial AQ
            aq_strength: Some(15), // AQ strength
            gop_size: Some(30), // 30 frame GOP
            video_profile: Some("high".to_string()), // H.264 high profile
            video_tune: Some("hq".to_string()), // High quality tune

            // Metadata defaults
            copy_metadata: true,
            mp4_optimize: true,
            add_videoai_metadata: true,
            disable_audio: false,
            hide_banner: true,
            high_quality_scaling: true,

            // Time control defaults
            start_time: None,
            duration: None,
            end_time: None,

            // Rate control - will be set below
            rate_control_mode: RateControlMode::ConstantQP(18),

            // Other defaults
            pre_scale: None,
            pre_filters: Vec::new(),
            preblur: Some(0),
            estimate: Some(8),
            enable_two_pass: false,
            temp_dir: None,
            prenoise: Some(0.02),
            target_fps: None,
            sdr_inflection_point: Some(0.7),
            hdr_ip_adjust: Some(0.0),
            saturation_adjust: Some(0.0),
            enable_hdr_colorspace: false,
        };
        
        // Set rate control mode
        options.rate_control_mode = match request.rate_control.as_str() {
            "constqp" => RateControlMode::ConstantQP(18),
            "cbr" => RateControlMode::ConstantBitrate("24M".to_string()),
            "vbr" => RateControlMode::VariableBitrate("20M".to_string()),
            "crf" => RateControlMode::CRF(18),
            _ => RateControlMode::ConstantQP(18),
        };
        
        // Set two-pass processing if requested
        if matches!(request.processing_mode, ProcessingMode::TwoPass) {
            options.enable_two_pass = true;
            options.temp_dir = Some("/tmp/tvai".to_string());
        }
        
        // Generate usage statistics
        let usage_stats = Self::calculate_usage_stats(&request.settings);
        
        match request.processing_mode {
            ProcessingMode::Single => {
                // Generate single command using a dummy template name
                let cmd = manager.generate_ffmpeg_command_from_template(
                    &template,
                    &request.input_file,
                    &request.output_file,
                    Some(&options)
                ).map_err(|e| format!("Failed to generate command: {}", e))?;
                
                Ok(GenerateCommandResponse {
                    success: true,
                    single_command: Some(cmd),
                    analysis_command: None,
                    processing_command: None,
                    usage_stats,
                    error: None,
                })
            }
            ProcessingMode::TwoPass => {
                let (analysis_cmd, processing_cmd) = manager.generate_two_pass_commands_from_template(
                    &template,
                    &request.input_file,
                    &request.output_file,
                    Some(&options)
                ).map_err(|e| format!("Failed to generate two-pass commands: {}", e))?;
                
                Ok(GenerateCommandResponse {
                    success: true,
                    single_command: None,
                    analysis_command: Some(analysis_cmd),
                    processing_command: Some(processing_cmd),
                    usage_stats,
                    error: None,
                })
            }
        }
    }
    
    fn web_settings_to_template(web_settings: &WebTopazSettings) -> Result<TopazTemplate, String> {
        // Convert web settings to internal TopazSettings format
        // This is a simplified conversion - in a real implementation,
        // you'd want to handle all the fields properly
        
        let settings = TopazSettings {
            stabilize: crate::config::StabilizeSettings {
                active: web_settings.stabilize.active,
                smooth: web_settings.stabilize.smooth,
                method: web_settings.stabilize.method,
                rsc: web_settings.stabilize.rsc,
                reduce_motion: web_settings.stabilize.reduce_motion > 0,
                reduce_motion_iteration: web_settings.stabilize.reduce_motion_iteration,
            },
            motionblur: crate::config::MotionBlurSettings {
                active: web_settings.motionblur.active,
                model: web_settings.motionblur.model.clone(),
                model_name: Some(web_settings.motionblur.model_name.clone()),
            },
            slowmo: crate::config::SlowMotionSettings {
                active: web_settings.slowmo.active,
                model: web_settings.slowmo.model.clone(),
                factor: web_settings.slowmo.factor,
                duplicate: web_settings.slowmo.duplicate,
                duplicate_threshold: web_settings.slowmo.duplicate_threshold as i32,
            },
            enhance: crate::config::EnhanceSettings {
                active: web_settings.enhance.active,
                model: web_settings.enhance.model.clone(),
                video_type: web_settings.enhance.video_type,
                auto: web_settings.enhance.auto,
                field_order: 0,
                compress: web_settings.enhance.compress,
                detail: web_settings.enhance.detail,
                sharpen: web_settings.enhance.sharpen,
                denoise: web_settings.enhance.denoise,
                dehalo: web_settings.enhance.dehalo,
                deblur: web_settings.enhance.deblur,
                add_noise: 0,
                recover_original_detail_value: web_settings.enhance.recover_original_detail_value,
                focus_fix_level: Some("Standard".to_string()),
                is_artemis: false,
                is_gaia: false,
                is_theia: false,
                is_proteus: false,
                is_iris: false,
                is_second_enhancement: Some(false),
            },
            grain: crate::config::GrainSettings {
                active: web_settings.grain.active,
                grain: web_settings.grain.grain,
                grain_size: web_settings.grain.grain_size,
            },
            output: crate::config::OutputSettings {
                active: web_settings.output.active,
                out_size_method: web_settings.output.out_size_method,
                crop_to_fit: web_settings.output.crop_to_fit,
                output_par: 0,
                out_fps: web_settings.output.out_fps,
                custom_resolution_priority: Some(2),
                lock_aspect_ratio: Some(web_settings.output.lock_aspect_ratio),
            },
            hdr: Some(crate::config::HdrSettings {
                active: web_settings.hdr.active,
                model: web_settings.hdr.model.clone(),
                auto: web_settings.hdr.auto,
                exposure: web_settings.hdr.exposure,
                saturation: web_settings.hdr.saturation,
                sdr_inflection_point: web_settings.hdr.sdr_inflection_point as f32,
                hdr_output_trc: 0,
                video_type: 0,
                field_order: 0,
            }),
            second_enhance: None,
            filter_manager: None,
        };
        
        Ok(TopazTemplate {
            name: "Web Generated Template".to_string(),
            description: "Template generated from web interface".to_string(),
            author: "Web Interface".to_string(),
            save_output_settings: false,
            date: "2024-01-29".to_string(),
            veaiversion: "1.0.0".to_string(),
            editable: true,
            enabled: true,
            path: None,
            settings,
        })
    }
    
    fn calculate_usage_stats(settings: &WebTopazSettings) -> UsageStats {
        let mut enabled_features = Vec::new();
        let mut filter_count = 0;
        
        if settings.stabilize.active {
            enabled_features.push("防抖 (tvai_stb)".to_string());
            filter_count += 1;
        }
        
        if settings.motionblur.active {
            enabled_features.push("运动模糊去除 (tvai_up thm-2)".to_string());
            filter_count += 1;
        }
        
        if settings.slowmo.active {
            enabled_features.push(format!("{}x 慢动作 (tvai_fi)", settings.slowmo.factor));
            filter_count += 1;
        }
        
        if settings.enhance.active {
            enabled_features.push(format!("AI 增强 (tvai_up {})", settings.enhance.model));
            filter_count += 1;
        }
        
        if settings.hdr.active {
            enabled_features.push("HDR 处理 (tvai_up hyp-1 + setparams)".to_string());
            filter_count += 2; // HDR processing + color space conversion
        }
        
        if settings.grain.active {
            enabled_features.push("颗粒效果".to_string());
        }
        
        let processing_complexity = match filter_count {
            0..=1 => "低",
            2..=3 => "中",
            _ => "高",
        }.to_string();
        
        let estimated_processing_time = match filter_count {
            0..=1 => "1-5 分钟",
            2..=3 => "5-15 分钟", 
            _ => "15+ 分钟",
        }.to_string();
        
        UsageStats {
            enabled_features,
            filter_count,
            parameter_usage_rate: 75.0, // Based on our analysis
            processing_complexity,
            estimated_processing_time,
        }
    }
}
