//! Topaz Video AI template system
//! 
//! This module provides complete support for Topaz Video AI templates,
//! allowing users to load, apply, and customize video processing presets
//! that match the official Topaz Video AI application.

use std::collections::HashMap;
use std::path::Path;
use serde::{Deserialize, Serialize};
use chrono::Utc;
use crate::core::TvaiError;
use crate::Result;
use crate::video::{VideoUpscaleParams, InterpolationParams, VideoEnhanceParams};
use crate::core::models::{UpscaleModel, InterpolationModel};

/// Complete Topaz Video AI template structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopazTemplate {
    /// Template name
    pub name: String,
    /// Template description
    pub description: String,
    /// Template author
    #[serde(default = "default_author")]
    pub author: String,
    /// Whether to save output settings
    #[serde(default)]
    pub save_output_settings: bool,
    /// Creation/modification date
    #[serde(default = "default_date")]
    pub date: String,
    /// Topaz Video AI version
    #[serde(default = "default_version")]
    pub veaiversion: String,
    /// Whether template is editable
    #[serde(default)]
    pub editable: bool,
    /// Whether template is enabled
    #[serde(default = "default_true")]
    pub enabled: bool,
    /// Optional file path
    #[serde(skip_serializing_if = "Option::is_none")]
    pub path: Option<String>,
    /// All processing settings
    pub settings: TopazSettings,
}

/// All processing settings for Topaz Video AI
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopazSettings {
    /// Stabilization settings
    #[serde(default)]
    pub stabilize: StabilizeSettings,
    /// Motion blur settings
    #[serde(default)]
    pub motionblur: MotionBlurSettings,
    /// Slow motion/interpolation settings
    #[serde(default)]
    pub slowmo: SlowMotionSettings,
    /// Enhancement settings
    #[serde(default)]
    pub enhance: EnhanceSettings,
    /// Grain settings
    #[serde(default)]
    pub grain: GrainSettings,
    /// Output settings
    #[serde(default)]
    pub output: OutputSettings,
    /// HDR settings (optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hdr: Option<HdrSettings>,
    /// Second enhancement settings (optional)
    #[serde(rename = "secondEnhance", skip_serializing_if = "Option::is_none")]
    pub second_enhance: Option<SecondEnhanceSettings>,
    /// Filter manager settings (optional)
    #[serde(rename = "filterManager", skip_serializing_if = "Option::is_none")]
    pub filter_manager: Option<FilterManagerSettings>,
}

/// Video stabilization settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StabilizeSettings {
    /// Whether stabilization is active
    #[serde(default)]
    pub active: bool,
    /// Smoothing level (0-100)
    #[serde(default = "default_smooth")]
    pub smooth: i32,
    /// Stabilization method (0=auto crop, 1=no crop)
    #[serde(default = "default_method")]
    pub method: i32,
    /// Rolling shutter correction
    #[serde(default)]
    pub rsc: bool,
    /// Reduce motion
    #[serde(rename = "reduceMotion", default)]
    pub reduce_motion: bool,
    /// Reduce motion iterations
    #[serde(rename = "reduceMotionIteration", default = "default_reduce_motion_iteration")]
    pub reduce_motion_iteration: i32,
}

/// Motion blur settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MotionBlurSettings {
    /// Whether motion blur is active
    #[serde(default)]
    pub active: bool,
    /// Motion blur model
    #[serde(default = "default_motion_blur_model")]
    pub model: String,
    /// Alternative model name field
    #[serde(rename = "modelName", skip_serializing_if = "Option::is_none")]
    pub model_name: Option<String>,
}

/// Slow motion/interpolation settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlowMotionSettings {
    /// Whether slow motion is active
    #[serde(default)]
    pub active: bool,
    /// Interpolation model
    #[serde(default = "default_slowmo_model")]
    pub model: String,
    /// Slow motion factor
    #[serde(default = "default_factor")]
    pub factor: i32,
    /// Whether to duplicate frames
    #[serde(default = "default_true")]
    pub duplicate: bool,
    /// Duplicate threshold
    #[serde(rename = "duplicateThreshold", default = "default_duplicate_threshold")]
    pub duplicate_threshold: i32,
}

/// Enhancement settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhanceSettings {
    /// Whether enhancement is active
    #[serde(default)]
    pub active: bool,
    /// Enhancement model
    #[serde(default = "default_enhance_model")]
    pub model: String,
    /// Video type (0=interlaced, 1=progressive)
    #[serde(rename = "videoType", default = "default_video_type")]
    pub video_type: i32,
    /// Auto enhancement level
    #[serde(default)]
    pub auto: i32,
    /// Field order
    #[serde(rename = "fieldOrder", default)]
    pub field_order: i32,
    /// Compression level
    #[serde(default)]
    pub compress: i32,
    /// Detail level
    #[serde(default)]
    pub detail: i32,
    /// Sharpen level
    #[serde(default)]
    pub sharpen: i32,
    /// Denoise level
    #[serde(default)]
    pub denoise: i32,
    /// Dehalo level
    #[serde(default)]
    pub dehalo: i32,
    /// Deblur level
    #[serde(default)]
    pub deblur: i32,
    /// Add noise level
    #[serde(rename = "addNoise", default)]
    pub add_noise: i32,
    /// Recover original detail value
    #[serde(rename = "recoverOriginalDetailValue", default = "default_recover_detail")]
    pub recover_original_detail_value: i32,
    /// Focus fix level
    #[serde(rename = "focusFixLevel", skip_serializing_if = "Option::is_none")]
    pub focus_fix_level: Option<String>,
    /// Model flags
    #[serde(rename = "isArtemis", default)]
    pub is_artemis: bool,
    #[serde(rename = "isGaia", default)]
    pub is_gaia: bool,
    #[serde(rename = "isTheia", default)]
    pub is_theia: bool,
    #[serde(rename = "isProteus", default)]
    pub is_proteus: bool,
    #[serde(rename = "isIris", default)]
    pub is_iris: bool,
    /// Second enhancement flag
    #[serde(rename = "isSecondEnhancement", skip_serializing_if = "Option::is_none")]
    pub is_second_enhancement: Option<bool>,
}

/// Grain settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GrainSettings {
    /// Whether grain is active
    #[serde(default)]
    pub active: bool,
    /// Grain amount
    #[serde(default = "default_grain")]
    pub grain: i32,
    /// Grain size
    #[serde(rename = "grainSize", default = "default_grain_size")]
    pub grain_size: i32,
}

/// Output settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutputSettings {
    /// Whether output settings are active
    #[serde(default = "default_true")]
    pub active: bool,
    /// Output size method
    #[serde(rename = "outSizeMethod", default)]
    pub out_size_method: i32,
    /// Whether to crop to fit
    #[serde(rename = "cropToFit", default)]
    pub crop_to_fit: bool,
    /// Output pixel aspect ratio
    #[serde(rename = "outputPAR", default)]
    pub output_par: i32,
    /// Output frame rate
    #[serde(rename = "outFPS", default)]
    pub out_fps: i32,
    /// Custom resolution priority
    #[serde(rename = "customResolutionPriority", skip_serializing_if = "Option::is_none")]
    pub custom_resolution_priority: Option<i32>,
    /// Lock aspect ratio
    #[serde(rename = "lockAspectRatio", skip_serializing_if = "Option::is_none")]
    pub lock_aspect_ratio: Option<bool>,
}

// Default value functions
fn default_author() -> String { "Topaz Labs".to_string() }
fn default_date() -> String { Utc::now().format("%a %b %d %H:%M:%S %Y GMT%z").to_string() }
fn default_version() -> String { "7.0.1".to_string() }
fn default_true() -> bool { true }
fn default_smooth() -> i32 { 50 }
fn default_method() -> i32 { 1 }
fn default_reduce_motion_iteration() -> i32 { 2 }
fn default_motion_blur_model() -> String { "thm-2".to_string() }
fn default_slowmo_model() -> String { "apo-8".to_string() }
fn default_factor() -> i32 { 1 }
fn default_duplicate_threshold() -> i32 { 10 }
fn default_enhance_model() -> String { "prob-4".to_string() }
fn default_video_type() -> i32 { 1 }
fn default_recover_detail() -> i32 { 20 }
fn default_grain() -> i32 { 5 }
fn default_grain_size() -> i32 { 2 }

/// HDR settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HdrSettings {
    /// Whether HDR is active
    #[serde(default)]
    pub active: bool,
    /// Auto HDR level
    #[serde(default)]
    pub auto: i32,
    /// Exposure adjustment
    #[serde(default)]
    pub exposure: i32,
    /// Field order
    #[serde(rename = "fieldOrder", default)]
    pub field_order: i32,
    /// HDR output transfer curve
    #[serde(rename = "hdrOutputTRC", default)]
    pub hdr_output_trc: i32,
    /// HDR model
    #[serde(default = "default_hdr_model")]
    pub model: String,
    /// Saturation adjustment
    #[serde(default)]
    pub saturation: i32,
    /// SDR inflection point
    #[serde(rename = "sdrInflectionPoint", default = "default_sdr_inflection")]
    pub sdr_inflection_point: f32,
    /// Video type
    #[serde(rename = "videoType", default = "default_video_type")]
    pub video_type: i32,
}

/// Second enhancement settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecondEnhanceSettings {
    /// Whether second enhancement is active
    #[serde(default)]
    pub active: bool,
    /// Enhancement model
    #[serde(default = "default_enhance_model")]
    pub model: String,
    /// Video type
    #[serde(rename = "videoType", default = "default_video_type")]
    pub video_type: i32,
    /// Auto enhancement level
    #[serde(default)]
    pub auto: i32,
    /// Field order
    #[serde(rename = "fieldOrder", default)]
    pub field_order: i32,
    /// Compression level
    #[serde(default)]
    pub compress: i32,
    /// Detail level
    #[serde(default)]
    pub detail: i32,
    /// Sharpen level
    #[serde(default)]
    pub sharpen: i32,
    /// Denoise level
    #[serde(default)]
    pub denoise: i32,
    /// Dehalo level
    #[serde(default)]
    pub dehalo: i32,
    /// Deblur level
    #[serde(default)]
    pub deblur: i32,
    /// Add noise level
    #[serde(rename = "addNoise", default)]
    pub add_noise: i32,
    /// Recover original detail value
    #[serde(rename = "recoverOriginalDetailValue", default = "default_recover_detail")]
    pub recover_original_detail_value: i32,
    /// Focus fix level
    #[serde(rename = "focusFixLevel", skip_serializing_if = "Option::is_none")]
    pub focus_fix_level: Option<String>,
}

/// Filter manager settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FilterManagerSettings {
    /// Whether second enhancement is enabled
    #[serde(rename = "SecondEnhancementEnabled", default)]
    pub second_enhancement_enabled: bool,
    /// Second enhancement intermediate resolution
    #[serde(rename = "SecondEnhancementIntermediateResolution", default = "default_intermediate_resolution")]
    pub second_enhancement_intermediate_resolution: i32,
}

// Additional default functions
fn default_hdr_model() -> String { "hyp-1".to_string() }
fn default_sdr_inflection() -> f32 { 0.7 }
fn default_intermediate_resolution() -> i32 { 3 }

/// Rate control modes for video encoding
#[derive(Debug, Clone)]
pub enum RateControlMode {
    /// Constant QP mode (-rc constqp -qp value)
    ConstantQP(u32),
    /// Constant bitrate mode (-rc cbr -b:v bitrate)
    ConstantBitrate(String),
    /// Variable bitrate mode (-rc vbr -b:v bitrate)
    VariableBitrate(String),
    /// CRF mode (-crf value)
    CRF(u32),
}

impl Default for RateControlMode {
    fn default() -> Self {
        RateControlMode::ConstantQP(18)
    }
}

/// Options for FFmpeg command generation
#[derive(Debug, Clone)]
pub struct FfmpegCommandOptions {
    /// Whether to overwrite output file
    pub overwrite: bool,
    /// Whether to use GPU acceleration
    pub use_gpu: bool,
    /// GPU type (nvidia, amd, intel)
    pub gpu_type: Option<String>,
    /// Video codec to use
    pub video_codec: Option<String>,
    /// Audio codec to use
    pub audio_codec: Option<String>,
    /// CRF value for quality
    pub crf: Option<u32>,
    /// Encoding preset
    pub preset: Option<String>,
    /// Pixel format
    pub pixel_format: Option<String>,
    /// Additional custom arguments
    pub custom_args: Vec<String>,

    // Topaz-specific parameters
    /// Topaz device ID (-2 = auto, -1 = CPU, 0+ = specific GPU)
    pub topaz_device: Option<i32>,
    /// VRAM usage strategy (0 = conservative, 1 = normal, 2 = aggressive)
    pub topaz_vram: Option<i32>,
    /// Number of processing instances
    pub topaz_instances: Option<i32>,
    /// Blend ratio for enhancement
    pub blend_ratio: Option<f32>,
    /// Duplicate detection threshold for interpolation
    pub duplicate_threshold: Option<f32>,

    // Advanced encoding options
    /// NVENC preset (p1-p7, p7 = highest quality)
    pub nvenc_preset: Option<String>,
    /// Use constant QP instead of CRF
    pub use_constqp: bool,
    /// QP value for constant QP mode
    pub qp_value: Option<u32>,
    /// Rate control lookahead frames
    pub lookahead: Option<u32>,
    /// Spatial adaptive quantization
    pub spatial_aq: Option<i32>,
    /// AQ strength
    pub aq_strength: Option<i32>,
    /// GOP size
    pub gop_size: Option<u32>,
    /// Video profile
    pub video_profile: Option<String>,
    /// Video tune
    pub video_tune: Option<String>,

    // Metadata and container options
    /// Copy metadata from input
    pub copy_metadata: bool,
    /// Optimize MP4 container
    pub mp4_optimize: bool,
    /// Add VideoAI metadata
    pub add_videoai_metadata: bool,
    /// Disable audio
    pub disable_audio: bool,
    /// Hide FFmpeg banner
    pub hide_banner: bool,
    /// Use high quality scaling
    pub high_quality_scaling: bool,

    // Time control parameters
    /// Start time offset in seconds
    pub start_time: Option<f64>,
    /// Duration to process in seconds
    pub duration: Option<f64>,
    /// End time in seconds
    pub end_time: Option<f64>,

    // Rate control mode
    /// Rate control mode
    pub rate_control_mode: RateControlMode,

    // Pre-processing
    /// Pre-scale before enhancement (width, height) -1 = auto
    pub pre_scale: Option<(u32, i32)>,
    /// Additional pre-processing filters
    pub pre_filters: Vec<String>,

    // Advanced tvai_up parameters
    /// Pre-blur level
    pub preblur: Option<i32>,
    /// Estimate parameter for tvai_up
    pub estimate: Option<i32>,

    /// Two-pass processing
    /// Enable two-pass processing (analysis + processing)
    pub enable_two_pass: bool,
    /// Temporary directory for analysis files
    pub temp_dir: Option<String>,

    /// Advanced filter parameters
    /// Pre-noise level for enhancement
    pub prenoise: Option<f32>,
    /// Target FPS for interpolation
    pub target_fps: Option<u32>,

    /// HDR parameters
    /// SDR inflection point
    pub sdr_inflection_point: Option<f32>,
    /// HDR inflection point adjustment
    pub hdr_ip_adjust: Option<f32>,
    /// Saturation adjustment
    pub saturation_adjust: Option<f32>,

    /// Color space settings
    /// Enable HDR color space output
    pub enable_hdr_colorspace: bool,
}

impl Default for FfmpegCommandOptions {
    fn default() -> Self {
        Self {
            overwrite: true,
            use_gpu: true,
            gpu_type: Some("nvidia".to_string()),
            video_codec: None,
            audio_codec: None,
            crf: Some(18),
            preset: Some("slow".to_string()),
            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 default
            rate_control_mode: RateControlMode::default(),

            // Pre-processing defaults
            pre_scale: None,
            pre_filters: Vec::new(),

            // Advanced tvai_up defaults
            preblur: Some(0),
            estimate: Some(8),

            // Two-pass defaults
            enable_two_pass: false,
            temp_dir: None,

            // Advanced filter defaults
            prenoise: Some(0.02),
            target_fps: None,

            // HDR defaults
            sdr_inflection_point: Some(0.7),
            hdr_ip_adjust: Some(0.13),
            saturation_adjust: Some(0.1),

            // Color space defaults
            enable_hdr_colorspace: false,
        }
    }
}

impl FfmpegCommandOptions {
    /// Create options for CPU encoding
    pub fn cpu() -> Self {
        Self {
            use_gpu: false,
            gpu_type: None,
            video_codec: Some("libx265".to_string()),
            ..Default::default()
        }
    }

    /// Create options for NVIDIA GPU encoding
    pub fn nvidia() -> Self {
        Self {
            use_gpu: true,
            gpu_type: Some("nvidia".to_string()),
            video_codec: Some("h264_nvenc".to_string()), // Use H.264 like real Topaz
            ..Default::default()
        }
    }

    /// Create options matching real Topaz Video AI output
    pub fn topaz_like() -> Self {
        Self {
            use_gpu: true,
            gpu_type: Some("nvidia".to_string()),
            video_codec: Some("h264_nvenc".to_string()),
            use_constqp: true,
            qp_value: Some(18),
            nvenc_preset: Some("p7".to_string()),
            video_profile: Some("high".to_string()),
            video_tune: Some("hq".to_string()),
            lookahead: Some(20),
            spatial_aq: Some(1),
            aq_strength: Some(15),
            gop_size: Some(30),
            disable_audio: true, // Like the real command
            ..Default::default()
        }
    }

    /// Create options for AMD GPU encoding
    pub fn amd() -> Self {
        Self {
            use_gpu: true,
            gpu_type: Some("amd".to_string()),
            video_codec: Some("hevc_amf".to_string()),
            ..Default::default()
        }
    }

    /// Create options for Intel GPU encoding
    pub fn intel() -> Self {
        Self {
            use_gpu: true,
            gpu_type: Some("intel".to_string()),
            video_codec: Some("hevc_qsv".to_string()),
            ..Default::default()
        }
    }

    /// Set quality level (0-51, lower is better)
    pub fn with_crf(mut self, crf: u32) -> Self {
        self.crf = Some(crf);
        self
    }

    /// Set encoding preset
    pub fn with_preset(mut self, preset: &str) -> Self {
        self.preset = Some(preset.to_string());
        self
    }

    /// Set custom video codec
    pub fn with_video_codec(mut self, codec: &str) -> Self {
        self.video_codec = Some(codec.to_string());
        self
    }

    /// Set custom audio codec
    pub fn with_audio_codec(mut self, codec: &str) -> Self {
        self.audio_codec = Some(codec.to_string());
        self
    }

    /// Add custom FFmpeg arguments
    pub fn with_custom_args(mut self, args: Vec<String>) -> Self {
        self.custom_args = args;
        self
    }

    /// Set QP value for constant QP mode
    pub fn with_qp_value(mut self, qp: u32) -> Self {
        self.qp_value = Some(qp);
        self.use_constqp = true;
        self
    }

    /// Set NVENC preset
    pub fn with_nvenc_preset(mut self, preset: &str) -> Self {
        self.nvenc_preset = Some(preset.to_string());
        self
    }

    /// Set blend ratio
    pub fn with_blend_ratio(mut self, blend: f32) -> Self {
        self.blend_ratio = Some(blend);
        self
    }

    /// Set Topaz device
    pub fn with_topaz_device(mut self, device: i32) -> Self {
        self.topaz_device = Some(device);
        self
    }

    /// Set time range for processing
    pub fn with_time_range(mut self, start: Option<f64>, duration: Option<f64>) -> Self {
        self.start_time = start;
        self.duration = duration;
        self
    }

    /// Set rate control mode
    pub fn with_rate_control(mut self, mode: RateControlMode) -> Self {
        self.rate_control_mode = mode;
        self
    }

    /// Set pre-scale dimensions
    pub fn with_pre_scale(mut self, width: u32, height: i32) -> Self {
        self.pre_scale = Some((width, height));
        self
    }

    /// Create CBR (constant bitrate) options
    pub fn cbr(bitrate: &str) -> Self {
        Self {
            rate_control_mode: RateControlMode::ConstantBitrate(bitrate.to_string()),
            ..Default::default()
        }
    }

    /// Create VBR (variable bitrate) options
    pub fn vbr(bitrate: &str) -> Self {
        Self {
            rate_control_mode: RateControlMode::VariableBitrate(bitrate.to_string()),
            ..Default::default()
        }
    }

    /// Enable two-pass processing like real Topaz
    pub fn with_two_pass(mut self, temp_dir: Option<String>) -> Self {
        self.enable_two_pass = true;
        self.temp_dir = temp_dir;
        self
    }

    /// Set HDR parameters
    pub fn with_hdr_params(mut self, sdr_ip: f32, hdr_adjust: f32, saturation: f32) -> Self {
        self.sdr_inflection_point = Some(sdr_ip);
        self.hdr_ip_adjust = Some(hdr_adjust);
        self.saturation_adjust = Some(saturation);
        self.enable_hdr_colorspace = true;
        self
    }

    /// Create options matching the third real command
    pub fn complex_processing() -> Self {
        Self {
            enable_two_pass: true,
            temp_dir: Some("/tmp/tvai".to_string()),
            rate_control_mode: RateControlMode::ConstantBitrate("24M".to_string()),
            nvenc_preset: Some("p6".to_string()),
            target_fps: Some(30),
            enable_hdr_colorspace: true,
            ..Default::default()
        }
    }
}

/// Applied template with converted parameters
#[derive(Debug, Clone)]
pub struct AppliedTemplate {
    /// Template name
    pub name: String,
    /// Template description
    pub description: String,
    /// Combined enhancement parameters
    pub enhance_params: VideoEnhanceParams,
    /// Whether stabilization is enabled
    pub stabilization_enabled: bool,
    /// Whether grain is enabled
    pub grain_enabled: bool,
    /// Output frame rate (if specified)
    pub output_fps: Option<f32>,
}

/// Topaz template manager
#[derive(Debug, Clone)]
pub struct TopazTemplateManager {
    templates: HashMap<String, TopazTemplate>,
}

impl Default for TopazTemplateManager {
    fn default() -> Self {
        let mut manager = Self {
            templates: HashMap::new(),
        };
        manager.load_builtin_templates();
        manager
    }
}

impl TopazTemplateManager {
    /// Create a new template manager
    pub fn new() -> Self {
        Self::default()
    }

    /// Load all builtin templates
    pub fn load_builtin_templates(&mut self) {
        for (name, template) in BuiltinTemplates::all() {
            self.templates.insert(name, template);
        }
    }

    /// Get template by name
    pub fn get_template(&self, name: &str) -> Option<&TopazTemplate> {
        self.templates.get(name)
    }

    /// List all template names
    pub fn list_templates(&self) -> Vec<String> {
        self.templates.keys().cloned().collect()
    }

    /// Add custom template
    pub fn add_template(&mut self, name: String, template: TopazTemplate) {
        self.templates.insert(name, template);
    }

    /// Remove template
    pub fn remove_template(&mut self, name: &str) -> Option<TopazTemplate> {
        self.templates.remove(name)
    }

    /// Load template from JSON string
    pub fn load_from_json(&mut self, name: String, json: &str) -> Result<()> {
        let template: TopazTemplate = serde_json::from_str(json)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to parse template JSON: {}", e)))?;

        // Validate template
        self.validate_template(&template)?;

        self.templates.insert(name, template);
        Ok(())
    }

    /// Load template from JSON file
    pub fn load_from_file<P: AsRef<Path>>(&mut self, name: String, path: P) -> Result<()> {
        let json = std::fs::read_to_string(path)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to read template file: {}", e)))?;
        self.load_from_json(name, &json)
    }

    /// Export template to JSON string
    pub fn export_to_json(&self, name: &str) -> Result<String> {
        if let Some(template) = self.templates.get(name) {
            serde_json::to_string_pretty(template)
                .map_err(|e| TvaiError::ConfigurationError(format!("Failed to serialize template: {}", e)))
        } else {
            Err(TvaiError::ConfigurationError("Template not found".to_string()))
        }
    }

    /// Export template to JSON file
    pub fn export_to_file<P: AsRef<Path>>(&self, name: &str, path: P) -> Result<()> {
        let json = self.export_to_json(name)?;
        std::fs::write(path, json)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to write template file: {}", e)))
    }

    /// Validate template settings
    pub fn validate_template(&self, template: &TopazTemplate) -> Result<()> {
        // Validate template name
        if template.name.is_empty() {
            return Err(TvaiError::ConfigurationError("Template name cannot be empty".to_string()));
        }

        // Validate enhancement model
        if template.settings.enhance.active {
            self.validate_enhance_model(&template.settings.enhance.model)?;
        }

        // Validate slow motion model
        if template.settings.slowmo.active {
            self.validate_slowmo_model(&template.settings.slowmo.model)?;
        }

        // Validate motion blur model
        if template.settings.motionblur.active {
            self.validate_motion_blur_model(&template.settings.motionblur.model)?;
        }

        // Validate output settings
        self.validate_output_settings(&template.settings.output)?;

        Ok(())
    }

    /// Validate enhancement model
    fn validate_enhance_model(&self, model: &str) -> Result<()> {
        let valid_models = [
            "iris-3", "iris-2", "ahq-12", "alq-13", "alqs-2", "amq-13", "amqs-2",
            "ghq-5", "nyx-3", "prob-4", "prob-3", "thf-4", "thd-3", "thm-2",
            "rhea-1", "rxl-1", "aaa-9", "ddv-3", "hyp-1"
        ];

        if !valid_models.contains(&model) {
            return Err(TvaiError::ConfigurationError(format!("Invalid enhancement model: {}", model)));
        }
        Ok(())
    }

    /// Validate slow motion model
    fn validate_slowmo_model(&self, model: &str) -> Result<()> {
        let valid_models = ["apo-8", "apf-1", "apf-2", "chr-2", "chf-3"];

        if !valid_models.contains(&model) {
            return Err(TvaiError::ConfigurationError(format!("Invalid slow motion model: {}", model)));
        }
        Ok(())
    }

    /// Validate motion blur model
    fn validate_motion_blur_model(&self, model: &str) -> Result<()> {
        let valid_models = ["thm-2"];

        if !valid_models.contains(&model) {
            return Err(TvaiError::ConfigurationError(format!("Invalid motion blur model: {}", model)));
        }
        Ok(())
    }

    /// Validate output settings
    fn validate_output_settings(&self, output: &OutputSettings) -> Result<()> {
        // Validate output size method
        if output.out_size_method < 0 || output.out_size_method > 10 {
            return Err(TvaiError::ConfigurationError(format!("Invalid output size method: {}", output.out_size_method)));
        }

        // Validate frame rate
        if output.out_fps < 0 || output.out_fps > 240 {
            return Err(TvaiError::ConfigurationError(format!("Invalid output frame rate: {}", output.out_fps)));
        }

        Ok(())
    }

    /// Parse template from examples directory
    pub fn parse_examples_template<P: AsRef<Path>>(path: P) -> Result<TopazTemplate> {
        let json = std::fs::read_to_string(path)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to read template file: {}", e)))?;

        let template: TopazTemplate = serde_json::from_str(&json)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to parse template JSON: {}", e)))?;

        Ok(template)
    }

    /// Load all templates from examples directory
    pub fn load_examples_templates<P: AsRef<Path>>(&mut self, examples_dir: P) -> Result<usize> {
        let dir = std::fs::read_dir(examples_dir)
            .map_err(|e| TvaiError::ConfigurationError(format!("Failed to read examples directory: {}", e)))?;

        let mut loaded_count = 0;

        for entry in dir {
            let entry = entry.map_err(|e| TvaiError::ConfigurationError(format!("Failed to read directory entry: {}", e)))?;
            let path = entry.path();

            if path.extension().and_then(|s| s.to_str()) == Some("json") {
                if let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) {
                    match Self::parse_examples_template(&path) {
                        Ok(template) => {
                            self.templates.insert(file_name.to_string(), template);
                            loaded_count += 1;
                        }
                        Err(e) => {
                            eprintln!("Warning: Failed to load template {}: {}", file_name, e);
                        }
                    }
                }
            }
        }

        Ok(loaded_count)
    }

    /// Generate FFmpeg command from template
    pub fn generate_ffmpeg_command(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
        options: Option<&FfmpegCommandOptions>
    ) -> Result<String> {
        let template = self.get_template(template_name)
            .ok_or_else(|| TvaiError::ConfigurationError(format!("Template '{}' not found", template_name)))?;

        let default_options = FfmpegCommandOptions::default();
        let opts = options.unwrap_or(&default_options);
        let mut cmd = Vec::new();

        // Base command
        cmd.push("ffmpeg".to_string());

        // Hide banner
        if opts.hide_banner {
            cmd.push("-hide_banner".to_string());
        }

        // Input options
        if opts.overwrite {
            cmd.push("-y".to_string());
        }

        // Time control
        if let Some(duration) = opts.duration {
            cmd.push("-t".to_string());
            cmd.push(duration.to_string());
        }

        if let Some(start_time) = opts.start_time {
            cmd.push("-ss".to_string());
            cmd.push(start_time.to_string());
        }

        // Hardware acceleration
        if opts.use_gpu {
            if let Some(gpu_type) = &opts.gpu_type {
                match gpu_type.as_str() {
                    "nvidia" => {
                        cmd.push("-hwaccel".to_string());
                        cmd.push("cuda".to_string());
                        cmd.push("-hwaccel_output_format".to_string());
                        cmd.push("cuda".to_string());
                    }
                    "amd" => {
                        cmd.push("-hwaccel".to_string());
                        cmd.push("d3d11va".to_string());
                    }
                    "intel" => {
                        cmd.push("-hwaccel".to_string());
                        cmd.push("qsv".to_string());
                    }
                    _ => {}
                }
            }
        }

        // High quality scaling flags
        if opts.high_quality_scaling {
            cmd.push("-sws_flags".to_string());
            cmd.push("spline+accurate_rnd+full_chroma_int".to_string());
        }

        // Input file
        cmd.push("-i".to_string());
        cmd.push(format!("\"{}\"", input_path));

        // Apply template settings
        self.apply_template_to_command(&mut cmd, template, opts)?;

        // Output file
        cmd.push(format!("\"{}\"", output_path));

        Ok(cmd.join(" "))
    }

    /// Apply template settings to FFmpeg command
    fn apply_template_to_command(
        &self,
        cmd: &mut Vec<String>,
        template: &TopazTemplate,
        opts: &FfmpegCommandOptions,
    ) -> Result<()> {
        // Video filters
        let mut filters = Vec::new();

        // Add pre-processing filters
        if let Some((width, height)) = opts.pre_scale {
            if height == -1 {
                filters.push(format!("scale={}:-1", width));
            } else {
                filters.push(format!("scale={}:{}", width, height));
            }
        }

        // Add custom pre-filters
        for filter in &opts.pre_filters {
            filters.push(filter.clone());
        }

        // Apply enhancement (upscaling)
        if template.settings.enhance.active {
            let model = &template.settings.enhance.model;
            let scale_factor = self.get_scale_factor_from_output_method(template.settings.output.out_size_method);

            // Topaz Video AI filter - more accurate to real command
            let mut tvai_filter = if scale_factor > 1.0 {
                format!("tvai_up=model={}:scale={}", model, scale_factor)
            } else {
                // Use specific resolution like real Topaz (scale=0 means use w:h)
                format!("tvai_up=model={}:scale=0", model)
            };

            // Add blend ratio
            if let Some(blend) = opts.blend_ratio {
                tvai_filter.push_str(&format!(":blend={}", blend));
            }

            // Add device and performance settings
            if let Some(device) = opts.topaz_device {
                tvai_filter.push_str(&format!(":device={}", device));
            }
            if let Some(vram) = opts.topaz_vram {
                tvai_filter.push_str(&format!(":vram={}", vram));
            }
            if let Some(instances) = opts.topaz_instances {
                tvai_filter.push_str(&format!(":instances={}", instances));
            }

            // Add preblur parameter
            if let Some(preblur) = opts.preblur {
                tvai_filter.push_str(&format!(":preblur={}", preblur));
            }

            // Add enhancement parameters (using new parameter names from real command)
            tvai_filter.push_str(&format!(":noise={}", template.settings.enhance.denoise));
            tvai_filter.push_str(&format!(":details={}", template.settings.enhance.detail));
            tvai_filter.push_str(&format!(":halo={}", template.settings.enhance.dehalo));
            tvai_filter.push_str(&format!(":blur={}", template.settings.enhance.deblur));
            tvai_filter.push_str(&format!(":compression={}", template.settings.enhance.compress));

            // Add estimate parameter
            if let Some(estimate) = opts.estimate {
                tvai_filter.push_str(&format!(":estimate={}", estimate));
            }

            filters.push(tvai_filter);
        }

        // Apply slow motion/interpolation
        if template.settings.slowmo.active {
            let model = &template.settings.slowmo.model;
            let factor = template.settings.slowmo.factor;

            let mut interpolation_filter = format!("tvai_fi=model={}:slowmo={}", model, factor);

            // Add duplicate threshold (rdt parameter)
            if let Some(rdt) = opts.duplicate_threshold {
                interpolation_filter.push_str(&format!(":rdt={}", rdt));
            }

            // Add device and performance settings
            if let Some(device) = opts.topaz_device {
                interpolation_filter.push_str(&format!(":device={}", device));
            }
            if let Some(vram) = opts.topaz_vram {
                interpolation_filter.push_str(&format!(":vram={}", vram));
            }
            if let Some(instances) = opts.topaz_instances {
                interpolation_filter.push_str(&format!(":instances={}", instances));
            }

            filters.push(interpolation_filter);
        }

        // Apply stabilization
        if template.settings.stabilize.active {
            let full_frame = if template.settings.stabilize.method == 0 { 0 } else { 1 };
            let smoothness = (template.settings.stabilize.smooth as f64 / 100.0 * 16.0).min(16.0);

            let stabilize_filter = format!("tvai_stb=model=ref-2:full={}:smoothness={:.1}", full_frame, smoothness);
            filters.push(stabilize_filter);
        }

        // Apply grain
        if template.settings.grain.active {
            let grain_amount = template.settings.grain.grain;
            let grain_size = template.settings.grain.grain_size;

            let grain_filter = format!("tvai_grain=amount={}:size={}", grain_amount, grain_size);
            filters.push(grain_filter);
        }

        // Add video filters if any
        if !filters.is_empty() {
            cmd.push("-vf".to_string());
            cmd.push(format!("\"{}\"", filters.join(",")));
        }

        // Apply output settings
        self.apply_output_settings_to_command(cmd, &template.settings.output, opts, template)?;

        Ok(())
    }

    /// Apply output settings to FFmpeg command
    fn apply_output_settings_to_command(
        &self,
        cmd: &mut Vec<String>,
        output: &OutputSettings,
        opts: &FfmpegCommandOptions,
        template: &TopazTemplate,
    ) -> Result<()> {
        // Video codec
        if let Some(codec) = &opts.video_codec {
            cmd.push("-c:v".to_string());
            cmd.push(codec.clone());
        } else if opts.use_gpu {
            // Default GPU codec
            if let Some(gpu_type) = &opts.gpu_type {
                match gpu_type.as_str() {
                    "nvidia" => {
                        cmd.push("-c:v".to_string());
                        cmd.push("h264_nvenc".to_string()); // Use H.264 like real Topaz
                    }
                    "amd" => {
                        cmd.push("-c:v".to_string());
                        cmd.push("h264_amf".to_string());
                    }
                    "intel" => {
                        cmd.push("-c:v".to_string());
                        cmd.push("h264_qsv".to_string());
                    }
                    _ => {
                        cmd.push("-c:v".to_string());
                        cmd.push("libx264".to_string());
                    }
                }
            }
        } else {
            cmd.push("-c:v".to_string());
            cmd.push("libx264".to_string());
        }

        // Video profile
        if let Some(profile) = &opts.video_profile {
            cmd.push("-profile:v".to_string());
            cmd.push(profile.clone());
        }

        // Pixel format
        if let Some(pix_fmt) = &opts.pixel_format {
            cmd.push("-pix_fmt".to_string());
            cmd.push(pix_fmt.clone());
        }

        // GOP size
        if let Some(gop) = opts.gop_size {
            cmd.push("-g".to_string());
            cmd.push(gop.to_string());
        }

        // NVENC preset (p1-p7)
        if let Some(nvenc_preset) = &opts.nvenc_preset {
            if opts.gpu_type.as_ref().map_or(false, |gpu| gpu == "nvidia") {
                cmd.push("-preset".to_string());
                cmd.push(nvenc_preset.clone());
            }
        } else if let Some(preset) = &opts.preset {
            cmd.push("-preset".to_string());
            cmd.push(preset.clone());
        }

        // Video tune
        if let Some(tune) = &opts.video_tune {
            cmd.push("-tune".to_string());
            cmd.push(tune.clone());
        }

        // Rate control (using new enum-based approach)
        match &opts.rate_control_mode {
            RateControlMode::ConstantQP(qp) => {
                cmd.push("-rc".to_string());
                cmd.push("constqp".to_string());
                cmd.push("-qp".to_string());
                cmd.push(qp.to_string());
            }
            RateControlMode::ConstantBitrate(bitrate) => {
                cmd.push("-rc".to_string());
                cmd.push("cbr".to_string());
                cmd.push("-b:v".to_string());
                cmd.push(bitrate.clone());
            }
            RateControlMode::VariableBitrate(bitrate) => {
                cmd.push("-rc".to_string());
                cmd.push("vbr".to_string());
                cmd.push("-b:v".to_string());
                cmd.push(bitrate.clone());
            }
            RateControlMode::CRF(crf) => {
                cmd.push("-crf".to_string());
                cmd.push(crf.to_string());
            }
        }

        // Advanced NVENC settings
        if opts.gpu_type.as_ref().map_or(false, |gpu| gpu == "nvidia") {
            if let Some(lookahead) = opts.lookahead {
                cmd.push("-rc-lookahead".to_string());
                cmd.push(lookahead.to_string());
            }

            if let Some(spatial_aq) = opts.spatial_aq {
                cmd.push("-spatial_aq".to_string());
                cmd.push(spatial_aq.to_string());
            }

            if let Some(aq_strength) = opts.aq_strength {
                cmd.push("-aq-strength".to_string());
                cmd.push(aq_strength.to_string());
            }

            // Disable bitrate control when using QP
            if opts.use_constqp {
                cmd.push("-b:v".to_string());
                cmd.push("0".to_string());
            }

            // B-frames
            cmd.push("-bf".to_string());
            cmd.push("0".to_string());
        }

        // Frame rate
        if output.out_fps > 0 {
            cmd.push("-r".to_string());
            cmd.push(output.out_fps.to_string());
        }

        // Quality settings
        if let Some(crf) = opts.crf {
            cmd.push("-crf".to_string());
            cmd.push(crf.to_string());
        }

        if let Some(preset) = &opts.preset {
            cmd.push("-preset".to_string());
            cmd.push(preset.clone());
        }

        // Audio handling
        if opts.disable_audio {
            cmd.push("-an".to_string());
        } else if let Some(audio_codec) = &opts.audio_codec {
            cmd.push("-c:a".to_string());
            cmd.push(audio_codec.clone());
        } else {
            cmd.push("-c:a".to_string());
            cmd.push("copy".to_string()); // Copy audio by default
        }

        // Metadata handling
        if opts.copy_metadata {
            cmd.push("-map_metadata".to_string());
            cmd.push("0".to_string());
            cmd.push("-map_metadata:s:v".to_string());
            cmd.push("0:s:v".to_string());
        }

        // FPS mode
        cmd.push("-fps_mode:v".to_string());
        cmd.push("passthrough".to_string());

        // MP4 optimization
        if opts.mp4_optimize {
            cmd.push("-movflags".to_string());
            cmd.push("frag_keyframe+empty_moov+delay_moov+use_metadata_tags+write_colr".to_string());
        }

        // VideoAI metadata
        if opts.add_videoai_metadata {
            let metadata = self.generate_videoai_metadata(template);
            cmd.push("-metadata".to_string());
            cmd.push(format!("videoai={}", metadata));
        }

        Ok(())
    }

    /// Generate FFmpeg command for quick processing
    pub fn quick_ffmpeg_command(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
    ) -> Result<String> {
        self.generate_ffmpeg_command(template_name, input_path, output_path, None)
    }

    /// Generate FFmpeg command with GPU acceleration
    pub fn gpu_ffmpeg_command(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
        gpu_type: &str,
    ) -> Result<String> {
        let options = match gpu_type {
            "nvidia" => FfmpegCommandOptions::nvidia(),
            "amd" => FfmpegCommandOptions::amd(),
            "intel" => FfmpegCommandOptions::intel(),
            _ => FfmpegCommandOptions::default(),
        };

        self.generate_ffmpeg_command(template_name, input_path, output_path, Some(&options))
    }

    /// Generate FFmpeg command for CPU processing
    pub fn cpu_ffmpeg_command(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
    ) -> Result<String> {
        let options = FfmpegCommandOptions::cpu();
        self.generate_ffmpeg_command(template_name, input_path, output_path, Some(&options))
    }

    /// Generate FFmpeg command with custom quality
    pub fn quality_ffmpeg_command(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
        crf: u32,
        preset: &str,
    ) -> Result<String> {
        let options = FfmpegCommandOptions::default()
            .with_crf(crf)
            .with_preset(preset);

        self.generate_ffmpeg_command(template_name, input_path, output_path, Some(&options))
    }

    /// Generate batch FFmpeg commands for multiple files
    pub fn batch_ffmpeg_commands(
        &self,
        template_name: &str,
        input_output_pairs: &[(String, String)],
        options: Option<&FfmpegCommandOptions>,
    ) -> Result<Vec<String>> {
        let mut commands = Vec::new();

        for (input, output) in input_output_pairs {
            let cmd = self.generate_ffmpeg_command(template_name, input, output, options)?;
            commands.push(cmd);
        }

        Ok(commands)
    }

    /// Generate two-pass FFmpeg commands like real Topaz
    pub fn generate_two_pass_commands(
        &self,
        template_name: &str,
        input_path: &str,
        output_path: &str,
        options: Option<&FfmpegCommandOptions>,
    ) -> Result<(String, String)> {
        let template = self.get_template(template_name)
            .ok_or_else(|| TvaiError::ConfigurationError(format!("Template '{}' not found", template_name)))?;

        let default_options = FfmpegCommandOptions::default();
        let opts = options.unwrap_or(&default_options);

        if !opts.enable_two_pass {
            // Fall back to single pass
            let single_cmd = self.generate_ffmpeg_command(template_name, input_path, output_path, options)?;
            return Ok((String::new(), single_cmd));
        }

        // Generate analysis pass command
        let analysis_cmd = self.generate_analysis_pass_command(template, input_path, opts)?;

        // Generate processing pass command
        let processing_cmd = self.generate_processing_pass_command(template, input_path, output_path, opts)?;

        Ok((analysis_cmd, processing_cmd))
    }

    /// Generate analysis pass command (first stage)
    fn generate_analysis_pass_command(
        &self,
        _template: &TopazTemplate,
        input_path: &str,
        opts: &FfmpegCommandOptions,
    ) -> Result<String> {
        let mut cmd = Vec::new();

        // Base command
        cmd.push("ffmpeg".to_string());

        if opts.hide_banner {
            cmd.push("-hide_banner".to_string());
        }

        // Time control
        if let Some(duration) = opts.duration {
            cmd.push("-t".to_string());
            cmd.push(duration.to_string());
        }

        if let Some(start_time) = opts.start_time {
            cmd.push("-ss".to_string());
            cmd.push(start_time.to_string());
        }

        // Input
        cmd.push("-i".to_string());
        cmd.push(format!("\"{}\"", input_path));

        // High quality scaling
        if opts.high_quality_scaling {
            cmd.push("-sws_flags".to_string());
            cmd.push("spline+accurate_rnd+full_chroma_int".to_string());
        }

        // Analysis filter
        let default_temp = "/tmp".to_string();
        let temp_dir = opts.temp_dir.as_ref().unwrap_or(&default_temp);
        let config_file = format!("{}/tvai_analysis.json", temp_dir);

        let analysis_filter = format!(
            "tvai_cpe=model=cpe-2:filename={}:device={}",
            config_file.replace(":", "\\:"),
            opts.topaz_device.unwrap_or(-2)
        );

        cmd.push("-filter_complex".to_string());
        cmd.push(format!("\"{}\"", analysis_filter));

        // Null output (analysis only)
        cmd.push("-f".to_string());
        cmd.push("null".to_string());
        cmd.push("-".to_string());

        Ok(cmd.join(" "))
    }

    /// Generate processing pass command (second stage)
    fn generate_processing_pass_command(
        &self,
        template: &TopazTemplate,
        input_path: &str,
        output_path: &str,
        opts: &FfmpegCommandOptions,
    ) -> Result<String> {
        let mut cmd = Vec::new();

        // Base command
        cmd.push("ffmpeg".to_string());

        if opts.hide_banner {
            cmd.push("-hide_banner".to_string());
        }

        // Additional flags for processing pass
        cmd.push("-nostdin".to_string());
        cmd.push("-y".to_string());
        cmd.push("-nostats".to_string());

        // Time control
        if let Some(duration) = opts.duration {
            cmd.push("-t".to_string());
            cmd.push(duration.to_string());
        }

        if let Some(start_time) = opts.start_time {
            cmd.push("-ss".to_string());
            cmd.push(start_time.to_string());
        }

        // Input
        cmd.push("-i".to_string());
        cmd.push(format!("\"{}\"", input_path));

        // High quality scaling
        if opts.high_quality_scaling {
            cmd.push("-sws_flags".to_string());
            cmd.push("spline+accurate_rnd+full_chroma_int".to_string());
        }

        // Complex filter chain
        let filter_chain = self.generate_complex_filter_chain(template, opts)?;
        cmd.push("-filter_complex".to_string());
        cmd.push(format!("\"{}\"", filter_chain));

        // Apply output settings
        self.apply_output_settings_to_command(&mut cmd, &template.settings.output, opts, template)?;

        // Output file
        cmd.push(format!("\"{}\"", output_path));

        Ok(cmd.join(" "))
    }

    /// Generate FFmpeg command from a template object
    pub fn generate_ffmpeg_command_from_template(
        &self,
        template: &TopazTemplate,
        input_path: &str,
        output_path: &str,
        options: Option<&FfmpegCommandOptions>,
    ) -> Result<String> {
        let default_options = FfmpegCommandOptions::default();
        let opts = options.unwrap_or(&default_options);

        let mut cmd = Vec::new();

        // Base command
        cmd.push("ffmpeg".to_string());

        // Hide banner
        if opts.hide_banner {
            cmd.push("-hide_banner".to_string());
        }

        // Input options
        if opts.overwrite {
            cmd.push("-y".to_string());
        }

        // Time control
        if let Some(duration) = opts.duration {
            cmd.push("-t".to_string());
            cmd.push(duration.to_string());
        }

        if let Some(start_time) = opts.start_time {
            cmd.push("-ss".to_string());
            cmd.push(start_time.to_string());
        }

        // High quality scaling flags
        if opts.high_quality_scaling {
            cmd.push("-sws_flags".to_string());
            cmd.push("spline+accurate_rnd+full_chroma_int".to_string());
        }

        // Input file
        cmd.push("-i".to_string());
        cmd.push(input_path.to_string());

        // Generate filters
        let filters = self.generate_filters_from_template(template, opts)?;
        if !filters.is_empty() {
            cmd.push("-vf".to_string());
            cmd.push(filters.join(","));
        }

        // Apply output settings
        self.apply_output_settings_to_command(&mut cmd, &template.settings.output, opts, template)?;

        // Output file
        cmd.push(output_path.to_string());

        Ok(cmd.join(" "))
    }

    /// Generate two-pass commands from a template object
    pub fn generate_two_pass_commands_from_template(
        &self,
        template: &TopazTemplate,
        input_path: &str,
        output_path: &str,
        options: Option<&FfmpegCommandOptions>,
    ) -> Result<(String, String)> {
        let default_options = FfmpegCommandOptions::default();
        let opts = options.unwrap_or(&default_options);

        if !opts.enable_two_pass {
            // Fall back to single pass
            let single_cmd = self.generate_ffmpeg_command_from_template(template, input_path, output_path, options)?;
            return Ok((String::new(), single_cmd));
        }

        // Generate analysis pass command
        let analysis_cmd = self.generate_analysis_pass_command(template, input_path, opts)?;

        // Generate processing pass command
        let processing_cmd = self.generate_processing_pass_command(template, input_path, output_path, opts)?;

        Ok((analysis_cmd, processing_cmd))
    }

    /// Generate filters from template
    fn generate_filters_from_template(
        &self,
        template: &TopazTemplate,
        opts: &FfmpegCommandOptions,
    ) -> Result<Vec<String>> {
        let mut filters = Vec::new();

        // Add pre-processing filters
        if let Some((width, height)) = opts.pre_scale {
            if height == -1 {
                filters.push(format!("scale={}:-1", width));
            } else {
                filters.push(format!("scale={}:{}", width, height));
            }
        }

        // Add custom pre-filters
        for filter in &opts.pre_filters {
            filters.push(filter.clone());
        }

        // Apply enhancement (upscaling)
        if template.settings.enhance.active {
            let model = &template.settings.enhance.model;
            let scale_factor = self.get_scale_factor_from_output_method(template.settings.output.out_size_method);

            let mut tvai_filter = if scale_factor > 1.0 {
                format!("tvai_up=model={}:scale={}", model, scale_factor)
            } else {
                format!("tvai_up=model={}:scale=0", model)
            };

            // Add blend ratio
            if let Some(blend) = opts.blend_ratio {
                tvai_filter.push_str(&format!(":blend={}", blend));
            }

            // Add device and performance settings
            if let Some(device) = opts.topaz_device {
                tvai_filter.push_str(&format!(":device={}", device));
            }
            if let Some(vram) = opts.topaz_vram {
                tvai_filter.push_str(&format!(":vram={}", vram));
            }
            if let Some(instances) = opts.topaz_instances {
                tvai_filter.push_str(&format!(":instances={}", instances));
            }

            // Add preblur parameter
            if let Some(preblur) = opts.preblur {
                tvai_filter.push_str(&format!(":preblur={}", preblur));
            }

            // Add enhancement parameters (using new parameter names from real command)
            tvai_filter.push_str(&format!(":noise={}", template.settings.enhance.denoise));
            tvai_filter.push_str(&format!(":details={}", template.settings.enhance.detail));
            tvai_filter.push_str(&format!(":halo={}", template.settings.enhance.dehalo));
            tvai_filter.push_str(&format!(":blur={}", template.settings.enhance.deblur));
            tvai_filter.push_str(&format!(":compression={}", template.settings.enhance.compress));

            // Add estimate parameter
            if let Some(estimate) = opts.estimate {
                tvai_filter.push_str(&format!(":estimate={}", estimate));
            }

            filters.push(tvai_filter);
        }

        // Apply slow motion/interpolation
        if template.settings.slowmo.active {
            let model = &template.settings.slowmo.model;
            let factor = template.settings.slowmo.factor;

            let mut interpolation_filter = format!("tvai_fi=model={}:slowmo={}", model, factor);

            // Add duplicate threshold (rdt parameter)
            if let Some(rdt) = opts.duplicate_threshold {
                interpolation_filter.push_str(&format!(":rdt={}", rdt));
            }

            // Add device and performance settings
            if let Some(device) = opts.topaz_device {
                interpolation_filter.push_str(&format!(":device={}", device));
            }
            if let Some(vram) = opts.topaz_vram {
                interpolation_filter.push_str(&format!(":vram={}", vram));
            }
            if let Some(instances) = opts.topaz_instances {
                interpolation_filter.push_str(&format!(":instances={}", instances));
            }

            filters.push(interpolation_filter);
        }

        // Apply stabilization
        if template.settings.stabilize.active {
            let full_frame = if template.settings.stabilize.method == 0 { 0 } else { 1 };
            let smoothness = (template.settings.stabilize.smooth as f64 / 100.0 * 16.0).min(16.0);

            let stabilization_filter = format!("tvai_stb=model=ref-2:full={}:smoothness={:.1}", full_frame, smoothness);
            filters.push(stabilization_filter);
        }

        // Apply grain
        if template.settings.grain.active {
            let grain_amount = template.settings.grain.grain;
            let grain_size = template.settings.grain.grain_size;

            let grain_filter = format!("tvai_grain=amount={}:size={}", grain_amount, grain_size);
            filters.push(grain_filter);
        }

        Ok(filters)
    }

    /// Generate complex filter chain like the third real command
    fn generate_complex_filter_chain(
        &self,
        template: &TopazTemplate,
        opts: &FfmpegCommandOptions,
    ) -> Result<String> {
        let mut filters = Vec::new();
        let default_temp = "/tmp".to_string();
        let temp_dir = opts.temp_dir.as_ref().unwrap_or(&default_temp);
        let config_file = format!("{}/tvai_analysis.json", temp_dir);

        // 1. Stabilization (tvai_stb)
        if template.settings.stabilize.active {
            let smoothness = template.settings.stabilize.smooth as f32 / 10.0; // Convert to 0-10 range
            let stb_filter = format!(
                "tvai_stb=model=ref-2:filename={}:smoothness={}:rst={}:wst=0:cache=128:dof=1111:ws=32:full=0:roll=1:reduce={}:device={}:vram={}:instances=1",
                config_file.replace(":", "\\:"),
                smoothness,
                if template.settings.stabilize.rsc { 1 } else { 0 },
                template.settings.stabilize.reduce_motion_iteration,
                opts.topaz_device.unwrap_or(-2),
                opts.topaz_vram.unwrap_or(1)
            );
            filters.push(stb_filter);
        }

        // 2. Motion blur removal (tvai_up with thm-2)
        if template.settings.motionblur.active {
            let mb_filter = format!(
                "tvai_up=model={}:scale=1:device={}:vram={}:instances=0",
                template.settings.motionblur.model,
                opts.topaz_device.unwrap_or(-2),
                opts.topaz_vram.unwrap_or(1)
            );
            filters.push(mb_filter);
        }

        // 3. Frame interpolation (tvai_fi)
        if template.settings.slowmo.active {
            let mut fi_filter = format!(
                "tvai_fi=model={}:slowmo={}",
                template.settings.slowmo.model,
                template.settings.slowmo.factor
            );

            if let Some(rdt) = opts.duplicate_threshold {
                fi_filter.push_str(&format!(":rdt={}", rdt));
            }

            if let Some(fps) = opts.target_fps {
                if fps > 0 {
                    fi_filter.push_str(&format!(":fps={}", fps));
                }
            }

            fi_filter.push_str(&format!(
                ":device={}:vram={}:instances=1",
                opts.topaz_device.unwrap_or(-2),
                opts.topaz_vram.unwrap_or(1)
            ));

            filters.push(fi_filter);
        }

        // 4. Pre-scaling
        if let Some((width, height)) = opts.pre_scale {
            if height == -1 {
                filters.push(format!("scale={}:-1", width));
            } else {
                filters.push(format!("scale={}:{}", width, height));
            }
        }

        // 5. Main enhancement (tvai_up with ghq-5 or similar)
        if template.settings.enhance.active {
            let model = &template.settings.enhance.model;
            let scale_factor = self.get_scale_factor_from_output_method(template.settings.output.out_size_method);

            let mut enhance_filter = format!("tvai_up=model={}:scale={}", model, scale_factor);

            // Add prenoise if available
            if let Some(prenoise) = opts.prenoise {
                enhance_filter.push_str(&format!(":prenoise={}", prenoise));
            }

            // Add grain parameters
            if template.settings.grain.active {
                enhance_filter.push_str(&format!(":grain={}", template.settings.grain.grain as f32 / 100.0));
                enhance_filter.push_str(&format!(":gsize={}", template.settings.grain.grain_size));
            }

            enhance_filter.push_str(&format!(
                ":device={}:vram={}:instances=1",
                opts.topaz_device.unwrap_or(-2),
                opts.topaz_vram.unwrap_or(1)
            ));

            filters.push(enhance_filter);
        }

        // 6. HDR processing (tvai_up with hyp-1)
        if let Some(hdr) = &template.settings.hdr {
            if hdr.active {
                let mut hdr_filter = format!("tvai_up=model={}:scale=1", hdr.model);

                // Add specific resolution if needed
                if template.settings.output.out_size_method > 0 {
                    hdr_filter.push_str(":w=1920:h=1088");
                }

                // Add complex HDR parameters
                if let (Some(sdr_ip), Some(hdr_adjust), Some(saturate)) = (
                    opts.sdr_inflection_point,
                    opts.hdr_ip_adjust,
                    opts.saturation_adjust,
                ) {
                    let params = format!("sdr_ip={}\\:hdr_ip_adjust={}\\:saturate={}", sdr_ip, hdr_adjust, saturate);
                    hdr_filter.push_str(&format!(":parameters='{}'", params));
                }

                // Add grain for HDR
                if template.settings.grain.active {
                    hdr_filter.push_str(&format!(":grain={}", template.settings.grain.grain as f32 / 100.0));
                    hdr_filter.push_str(&format!(":gsize={}", template.settings.grain.grain_size));
                }

                hdr_filter.push_str(&format!(
                    ":device={}:vram={}:instances=1",
                    opts.topaz_device.unwrap_or(-2),
                    opts.topaz_vram.unwrap_or(1)
                ));

                filters.push(hdr_filter);
            }
        }

        // 7. Color space conversion (setparams)
        if opts.enable_hdr_colorspace {
            filters.push("setparams=range=pc:color_primaries=bt2020:color_trc=smpte2084:colorspace=bt2020nc".to_string());
        }

        Ok(filters.join(","))
    }

    /// Generate VideoAI metadata string like real Topaz (complex version)
    fn generate_videoai_metadata(&self, template: &TopazTemplate) -> String {
        let mut metadata_parts = Vec::new();

        // Stabilization info (detailed like third command)
        if template.settings.stabilize.active {
            let smoothness = template.settings.stabilize.smooth;
            let mut stab_parts = vec![format!("Stabilized auto-crop")];

            if template.settings.stabilize.rsc {
                stab_parts.push("fixing rolling shutter".to_string());
            }

            stab_parts.push(format!("and with smoothness {}", smoothness));
            metadata_parts.push(stab_parts.join(" "));
        }

        // Motion blur info
        if template.settings.motionblur.active {
            let model = &template.settings.motionblur.model;
            metadata_parts.push(format!("Motion blur removed using {}", model));
        }

        // Slow motion info (with frame rate)
        if template.settings.slowmo.active {
            let factor = template.settings.slowmo.factor;
            let model = &template.settings.slowmo.model;
            let percentage = factor * 100;

            let mut slowmo_parts = vec![format!("Slowmo {}%", percentage)];

            // Add frame rate info if available
            slowmo_parts.push("and framerate changed to 30".to_string());
            slowmo_parts.push(format!("using {} replacing duplicate frames", model));

            metadata_parts.push(slowmo_parts.join(" "));
        }

        // Enhancement info (detailed)
        if template.settings.enhance.active {
            let model = &template.settings.enhance.model;
            let mut enhance_parts = vec![format!("Enhanced using {}", model)];

            // Add noise info if present
            if template.settings.enhance.denoise > 0 {
                enhance_parts.push(format!("and add noise at {}", template.settings.enhance.denoise));
            }

            metadata_parts.push(enhance_parts.join("; "));
        }

        // HDR info (new for third command)
        if let Some(hdr) = &template.settings.hdr {
            if hdr.active {
                let model = &hdr.model;
                let mut hdr_parts = vec![format!("HDR Enhanced using {}", model)];

                // Add HDR parameters
                hdr_parts.push(format!("exposure at {}", hdr.exposure as f32 / 100.0));
                hdr_parts.push(format!("saturation at {}", hdr.saturation as f32 / 100.0));
                hdr_parts.push(format!("and highlight threshold at {}", hdr.sdr_inflection_point as f32 / 100.0));

                metadata_parts.push(hdr_parts.join("; "));
            }
        }

        // Grain info
        if template.settings.grain.active {
            metadata_parts.push(format!("Grain added ({})", template.settings.grain.grain));
        }

        if metadata_parts.is_empty() {
            format!("Processed with template: {}", template.name)
        } else {
            metadata_parts.join(". ")
        }
    }

    /// Apply template to create video processing parameters
    pub fn apply_template(&self, template_name: &str) -> Result<AppliedTemplate> {
        let template = self.get_template(template_name)
            .ok_or_else(|| TvaiError::ConfigurationError(format!("Template '{}' not found", template_name)))?;

        let mut upscale_params = None;
        let mut interpolation_params = None;

        // Convert enhancement settings
        if template.settings.enhance.active {
            let model = self.parse_upscale_model(&template.settings.enhance.model)?;
            let scale_factor = self.get_scale_factor_from_output_method(template.settings.output.out_size_method);

            upscale_params = Some(VideoUpscaleParams {
                scale_factor,
                model,
                compression: template.settings.enhance.compress as f32 / 100.0,
                blend: 0.1, // Default blend value
                quality_preset: crate::config::QualityPreset::HighQuality,
                noise: template.settings.enhance.denoise as f32,
                details: template.settings.enhance.detail as f32,
                halo: template.settings.enhance.dehalo as f32,
                blur: template.settings.enhance.deblur as f32,
                ..Default::default()
            });
        }

        // Convert slow motion/interpolation settings
        if template.settings.slowmo.active {
            let model = self.parse_interpolation_model(&template.settings.slowmo.model)?;

            interpolation_params = Some(InterpolationParams {
                input_fps: 30, // Default input fps, should be detected from video
                multiplier: template.settings.slowmo.factor as f32,
                model,
                target_fps: if template.settings.output.out_fps > 0 {
                    Some(template.settings.output.out_fps as u32)
                } else {
                    None
                },
            });
        }

        let applied = AppliedTemplate {
            name: template.name.clone(),
            description: template.description.clone(),
            enhance_params: VideoEnhanceParams {
                upscale: upscale_params,
                interpolation: interpolation_params,
            },
            stabilization_enabled: template.settings.stabilize.active,
            grain_enabled: template.settings.grain.active,
            output_fps: if template.settings.output.out_fps > 0 {
                Some(template.settings.output.out_fps as f32)
            } else {
                None
            },
        };

        Ok(applied)
    }

    /// Parse upscale model from string
    fn parse_upscale_model(&self, model_str: &str) -> Result<UpscaleModel> {
        match model_str {
            "iris-3" => Ok(UpscaleModel::Iris3),
            "iris-2" => Ok(UpscaleModel::Iris2),
            "ahq-12" => Ok(UpscaleModel::Ahq12),
            "alq-13" => Ok(UpscaleModel::Alq13),
            "alqs-2" => Ok(UpscaleModel::Alqs2),
            "amq-13" => Ok(UpscaleModel::Amq13),
            "amqs-2" => Ok(UpscaleModel::Amqs2),
            "ghq-5" => Ok(UpscaleModel::Ghq5),
            "nyx-3" => Ok(UpscaleModel::Nyx3),
            "prob-4" => Ok(UpscaleModel::Prob4),
            "prob-3" => Ok(UpscaleModel::Prob4), // Map prob-3 to prob-4
            "thf-4" => Ok(UpscaleModel::Thf4),
            "thd-3" => Ok(UpscaleModel::Thd3),
            "thm-2" => Ok(UpscaleModel::Thm2),
            "rhea-1" => Ok(UpscaleModel::Rhea1),
            "rxl-1" => Ok(UpscaleModel::Rxl1),
            "aaa-9" => Ok(UpscaleModel::Aaa9),
            "ddv-3" => Ok(UpscaleModel::Prob4), // Map ddv-3 to prob-4 for compatibility
            _ => Err(TvaiError::ConfigurationError(format!("Unknown upscale model: {}", model_str))),
        }
    }

    /// Parse interpolation model from string
    fn parse_interpolation_model(&self, model_str: &str) -> Result<InterpolationModel> {
        match model_str {
            "apo-8" => Ok(InterpolationModel::Apo8),
            "apf-1" => Ok(InterpolationModel::Apf1),
            "apf-2" => Ok(InterpolationModel::Apf2),
            "chr-2" => Ok(InterpolationModel::Chr2),
            "chf-3" => Ok(InterpolationModel::Chf3),
            _ => Err(TvaiError::ConfigurationError(format!("Unknown interpolation model: {}", model_str))),
        }
    }

    /// Get scale factor from output size method
    fn get_scale_factor_from_output_method(&self, method: i32) -> f32 {
        match method {
            0 => 1.0,  // Original size
            6 => 2.0,  // FHD (assuming from lower resolution)
            7 => 4.0,  // 4K (assuming from 1080p)
            _ => 2.0,  // Default to 2x
        }
    }
}

/// Built-in templates from examples
pub struct BuiltinTemplates;

impl BuiltinTemplates {
    /// Get all builtin templates
    pub fn all() -> HashMap<String, TopazTemplate> {
        let mut templates = HashMap::new();

        // Add all builtin templates
        templates.insert("upscale_to_4k".to_string(), Self::upscale_to_4k());
        templates.insert("convert_to_60fps".to_string(), Self::convert_to_60fps());
        templates.insert("remove_noise".to_string(), Self::remove_noise());
        templates.insert("4x_slow_motion".to_string(), Self::slow_motion_4x());
        templates.insert("8x_super_slow_motion".to_string(), Self::slow_motion_8x());
        templates.insert("auto_crop_stabilization".to_string(), Self::auto_crop_stabilization());
        templates.insert("deinterlace_upscale_fhd".to_string(), Self::deinterlace_upscale_fhd());
        templates.insert("film_stock_4k_light".to_string(), Self::film_stock_4k_light());
        templates.insert("film_stock_4k_medium".to_string(), Self::film_stock_4k_medium());
        templates.insert("film_stock_4k_strong".to_string(), Self::film_stock_4k_strong());
        templates.insert("minidv_hd_int_basic".to_string(), Self::minidv_hd_int_basic());
        templates.insert("upscale_to_fhd".to_string(), Self::upscale_to_fhd());
        templates.insert("upscale_4k_convert_60fps".to_string(), Self::upscale_4k_convert_60fps());

        templates
    }

    /// Upscale to 4K template
    pub fn upscale_to_4k() -> TopazTemplate {
        TopazTemplate {
            name: "放大至4K".to_string(),
            description: "将视频分辨率放大至4K分辨率，同时增强画质。".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings::default(),
                enhance: EnhanceSettings {
                    active: true,
                    model: "prob-4".to_string(),
                    video_type: 1,
                    is_proteus: true,
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings {
                    active: true,
                    out_size_method: 7, // 4K upscale
                    ..Default::default()
                },
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// Convert to 60 FPS template
    pub fn convert_to_60fps() -> TopazTemplate {
        TopazTemplate {
            name: "转换至60帧".to_string(),
            description: "将视频素材的帧率转换为60fps，同时保持原始分辨率".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings {
                    active: true,
                    model: "chf-3".to_string(),
                    ..Default::default()
                },
                enhance: EnhanceSettings {
                    model: "prob-3".to_string(),
                    is_proteus: true,
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings {
                    active: true,
                    out_fps: 60,
                    ..Default::default()
                },
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// Remove noise template
    pub fn remove_noise() -> TopazTemplate {
        TopazTemplate {
            name: "去除噪点".to_string(),
            description: "使用Nyx模型精确去除视频噪点".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Mon Jun 10 20:45:00 2024 GMT-0500".to_string(),
            veaiversion: "5.1.2".to_string(),
            editable: false,
            enabled: true,
            path: Some("C:/ProgramData/Topaz Labs LLC/Topaz Video AI/presets/Remove noise.json".to_string()),
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings::default(),
                enhance: EnhanceSettings {
                    active: true,
                    model: "nyx-3".to_string(),
                    video_type: 1,
                    focus_fix_level: Some("Off".to_string()),
                    is_second_enhancement: Some(false),
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings {
                    active: true,
                    lock_aspect_ratio: Some(true),
                    custom_resolution_priority: Some(0),
                    ..Default::default()
                },
                hdr: None,
                second_enhance: None,
                filter_manager: Some(FilterManagerSettings {
                    second_enhancement_enabled: false,
                    second_enhancement_intermediate_resolution: 3,
                }),
            },
        }
    }

    /// 4x slow motion template
    pub fn slow_motion_4x() -> TopazTemplate {
        TopazTemplate {
            name: "4倍慢动作".to_string(),
            description: "对视频素材应用4倍（400%）慢动作效果".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings {
                    active: true,
                    model: "apo-8".to_string(),
                    factor: 4,
                    ..Default::default()
                },
                enhance: EnhanceSettings {
                    model: "prob-3".to_string(),
                    is_proteus: true,
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings::default(),
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// 8x super slow motion template
    pub fn slow_motion_8x() -> TopazTemplate {
        TopazTemplate {
            name: "8倍超级慢动作".to_string(),
            description: "对视频素材应用8倍（800%）超级慢动作效果".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings {
                    active: true,
                    model: "apo-8".to_string(),
                    factor: 8,
                    ..Default::default()
                },
                enhance: EnhanceSettings {
                    model: "prob-3".to_string(),
                    is_proteus: true,
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings::default(),
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// Auto crop stabilization template
    pub fn auto_crop_stabilization() -> TopazTemplate {
        TopazTemplate {
            name: "自动裁剪防抖".to_string(),
            description: "对抖动的视频素材应用自动裁剪防抖功能".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings {
                    active: true,
                    method: 0, // Auto crop
                    ..Default::default()
                },
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings::default(),
                enhance: EnhanceSettings {
                    model: "prob-3".to_string(),
                    is_proteus: true,
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings::default(),
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// Deinterlace and upscale to FHD template
    pub fn deinterlace_upscale_fhd() -> TopazTemplate {
        TopazTemplate {
            name: "去隔行扫描并放大至全高清".to_string(),
            description: "对视频素材进行去隔行扫描处理并放大至全高清分辨率".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Tue Jul 11 12:00:00 2023 GMT-0500".to_string(),
            veaiversion: "3.3.5".to_string(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                stabilize: StabilizeSettings::default(),
                motionblur: MotionBlurSettings::default(),
                slowmo: SlowMotionSettings {
                    model: "chf-3".to_string(),
                    ..Default::default()
                },
                enhance: EnhanceSettings {
                    active: true,
                    model: "ddv-3".to_string(),
                    video_type: 0, // Interlaced
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings {
                    active: true,
                    out_size_method: 6, // FHD upscale
                    ..Default::default()
                },
                hdr: None,
                second_enhance: None,
                filter_manager: None,
            },
        }
    }

    /// Film Stock 4K Strong template
    pub fn film_stock_4k_strong() -> TopazTemplate {
        TopazTemplate {
            name: "胶片素材4K强度处理".to_string(),
            description: "对胶片素材进行强度4K增强处理，最大化画质提升".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: "Fri Jun 6 11:37:31 2025 GMT-0500".to_string(),
            veaiversion: "7.0.1".to_string(),
            editable: false,
            enabled: true,
            path: Some("C:/ProgramData/Topaz Labs LLC/Topaz Video AI/presets/Film Stock 4K Strong.json".to_string()),
            settings: TopazSettings {
                stabilize: StabilizeSettings {
                    active: true,
                    ..Default::default()
                },
                motionblur: MotionBlurSettings {
                    model_name: Some("thm-2".to_string()),
                    ..Default::default()
                },
                slowmo: SlowMotionSettings::default(),
                enhance: EnhanceSettings {
                    active: true,
                    model: "alq-13".to_string(),
                    video_type: 1,
                    focus_fix_level: Some("Off".to_string()),
                    is_second_enhancement: Some(false),
                    ..Default::default()
                },
                grain: GrainSettings::default(),
                output: OutputSettings {
                    active: true,
                    out_size_method: 7, // 4K
                    custom_resolution_priority: Some(2),
                    lock_aspect_ratio: Some(true),
                    ..Default::default()
                },
                hdr: Some(HdrSettings {
                    model: "hyp-1".to_string(),
                    sdr_inflection_point: 0.7,
                    video_type: 1,
                    ..Default::default()
                }),
                second_enhance: Some(SecondEnhanceSettings {
                    active: true,
                    model: "prob-4".to_string(),
                    auto: 1,
                    compress: 15,
                    detail: 100,
                    sharpen: 100,
                    video_type: 1,
                    focus_fix_level: Some("Off".to_string()),
                    ..Default::default()
                }),
                filter_manager: None,
            },
        }
    }

    // Placeholder implementations for remaining templates
    pub fn film_stock_4k_light() -> TopazTemplate {
        let mut template = Self::film_stock_4k_strong();
        template.name = "胶片素材4K轻度处理".to_string();
        template.description = "对胶片素材进行轻度4K增强处理".to_string();
        // Reduce enhancement intensity
        if let Some(ref mut second_enhance) = template.settings.second_enhance {
            second_enhance.compress = 5;
            second_enhance.detail = 30;
            second_enhance.sharpen = 30;
        }
        template
    }

    pub fn film_stock_4k_medium() -> TopazTemplate {
        let mut template = Self::film_stock_4k_strong();
        template.name = "胶片素材4K中度处理".to_string();
        template.description = "对胶片素材进行中度4K增强处理".to_string();
        // Medium enhancement intensity
        if let Some(ref mut second_enhance) = template.settings.second_enhance {
            second_enhance.compress = 10;
            second_enhance.detail = 65;
            second_enhance.sharpen = 65;
        }
        template
    }

    pub fn minidv_hd_int_basic() -> TopazTemplate {
        TopazTemplate {
            name: "MiniDV HD基础处理".to_string(),
            description: "对MiniDV HD素材进行基础增强处理".to_string(),
            author: "Topaz Labs".to_string(),
            save_output_settings: false,
            date: default_date(),
            veaiversion: default_version(),
            editable: false,
            enabled: true,
            path: None,
            settings: TopazSettings {
                enhance: EnhanceSettings {
                    active: true,
                    model: "ddv-3".to_string(),
                    video_type: 0, // Interlaced
                    ..Default::default()
                },
                output: OutputSettings {
                    active: true,
                    out_size_method: 6, // HD
                    ..Default::default()
                },
                ..Default::default()
            },
        }
    }

    pub fn upscale_to_fhd() -> TopazTemplate {
        let mut template = Self::upscale_to_4k();
        template.name = "放大至全高清".to_string();
        template.description = "将视频分辨率放大至全高清分辨率".to_string();
        template.settings.output.out_size_method = 6; // FHD instead of 4K
        template
    }

    pub fn upscale_4k_convert_60fps() -> TopazTemplate {
        let mut template = Self::upscale_to_4k();
        template.name = "放大至4K并转换为60帧".to_string();
        template.description = "将视频放大至4K分辨率并转换为60fps".to_string();
        template.settings.slowmo.active = true;
        template.settings.slowmo.model = "chf-3".to_string();
        template.settings.output.out_fps = 60;
        template
    }
}

// Implement Default for all settings structs
impl Default for StabilizeSettings {
    fn default() -> Self {
        Self {
            active: false,
            smooth: default_smooth(),
            method: default_method(),
            rsc: false,
            reduce_motion: false,
            reduce_motion_iteration: default_reduce_motion_iteration(),
        }
    }
}

impl Default for MotionBlurSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: default_motion_blur_model(),
            model_name: None,
        }
    }
}

impl Default for SlowMotionSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: default_slowmo_model(),
            factor: default_factor(),
            duplicate: default_true(),
            duplicate_threshold: default_duplicate_threshold(),
        }
    }
}

impl Default for EnhanceSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: default_enhance_model(),
            video_type: default_video_type(),
            auto: 0,
            field_order: 0,
            compress: 0,
            detail: 0,
            sharpen: 0,
            denoise: 0,
            dehalo: 0,
            deblur: 0,
            add_noise: 0,
            recover_original_detail_value: default_recover_detail(),
            focus_fix_level: None,
            is_artemis: false,
            is_gaia: false,
            is_theia: false,
            is_proteus: false,
            is_iris: false,
            is_second_enhancement: None,
        }
    }
}

impl Default for GrainSettings {
    fn default() -> Self {
        Self {
            active: false,
            grain: default_grain(),
            grain_size: default_grain_size(),
        }
    }
}

impl Default for OutputSettings {
    fn default() -> Self {
        Self {
            active: default_true(),
            out_size_method: 0,
            crop_to_fit: false,
            output_par: 0,
            out_fps: 0,
            custom_resolution_priority: None,
            lock_aspect_ratio: None,
        }
    }
}

impl Default for HdrSettings {
    fn default() -> Self {
        Self {
            active: false,
            auto: 0,
            exposure: 0,
            field_order: 0,
            hdr_output_trc: 0,
            model: default_hdr_model(),
            saturation: 0,
            sdr_inflection_point: default_sdr_inflection(),
            video_type: default_video_type(),
        }
    }
}

impl Default for SecondEnhanceSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: default_enhance_model(),
            video_type: default_video_type(),
            auto: 0,
            field_order: 0,
            compress: 0,
            detail: 0,
            sharpen: 0,
            denoise: 0,
            dehalo: 0,
            deblur: 0,
            add_noise: 0,
            recover_original_detail_value: default_recover_detail(),
            focus_fix_level: None,
        }
    }
}

impl Default for TopazSettings {
    fn default() -> Self {
        Self {
            stabilize: StabilizeSettings::default(),
            motionblur: MotionBlurSettings::default(),
            slowmo: SlowMotionSettings::default(),
            enhance: EnhanceSettings::default(),
            grain: GrainSettings::default(),
            output: OutputSettings::default(),
            hdr: None,
            second_enhance: None,
            filter_manager: None,
        }
    }
}

/// Global template manager instance
static GLOBAL_TOPAZ_TEMPLATES: std::sync::OnceLock<std::sync::Mutex<TopazTemplateManager>> = std::sync::OnceLock::new();

/// Get global template manager
pub fn global_topaz_templates() -> &'static std::sync::Mutex<TopazTemplateManager> {
    GLOBAL_TOPAZ_TEMPLATES.get_or_init(|| std::sync::Mutex::new(TopazTemplateManager::new()))
}
