use serde::{Deserialize, Serialize};
use crate::error::TvaiError;

/// Topaz Video AI Template
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Template {
    /// Template name
    pub name: String,
    /// Template description
    pub description: String,
    /// Template author
    pub author: String,
    /// Creation date
    pub date: String,
    /// Topaz Video AI version
    #[serde(rename = "veaiversion")]
    pub veai_version: String,
    /// Whether template is editable
    pub editable: bool,
    /// Whether template is enabled
    pub enabled: bool,
    /// Whether to save output settings
    #[serde(rename = "saveOutputSettings")]
    pub save_output_settings: bool,
    /// Template file path (optional)
    pub path: Option<String>,
    /// Template settings
    pub settings: TemplateSettings,
}

/// Template settings containing all processing modules
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateSettings {
    /// Video stabilization settings
    pub stabilize: StabilizeSettings,
    /// Motion blur settings
    #[serde(rename = "motionblur")]
    pub motion_blur: MotionBlurSettings,
    /// Slow motion/frame interpolation settings
    #[serde(rename = "slowmo")]
    pub slow_motion: SlowMotionSettings,
    /// Video enhancement settings
    pub enhance: EnhanceSettings,
    /// Grain effect settings
    pub grain: GrainSettings,
    /// Output settings
    pub output: OutputSettings,
    /// Filter manager settings (optional, for newer versions)
    #[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
    pub active: bool,
    /// Smoothness level (0-100)
    pub smooth: i32,
    /// Stabilization method (0: auto crop, 1: full frame)
    pub method: i32,
    /// Rolling shutter correction
    pub rsc: bool,
    /// Reduce motion
    #[serde(rename = "reduceMotion")]
    pub reduce_motion: bool,
    /// Reduce motion iteration count
    #[serde(rename = "reduceMotionIteration")]
    pub reduce_motion_iteration: i32,
}

/// Motion blur settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MotionBlurSettings {
    /// Whether motion blur is active
    pub active: bool,
    /// Motion blur model
    pub model: String,
}

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

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

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

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

    // Extended FFmpeg output parameters
    /// Custom output width (overrides size method if set)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub width: Option<i32>,
    /// Custom output height (overrides size method if set)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub height: Option<i32>,
    /// Video codec (e.g., "libx264", "hevc_nvenc", "h264_amf")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub codec: Option<String>,
    /// Video bitrate in kbps (e.g., 5000 for 5Mbps)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub bitrate: Option<i32>,
    /// Constant Rate Factor for quality-based encoding (0-51, lower = better quality)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub crf: Option<i32>,
    /// Encoding preset (e.g., "ultrafast", "fast", "medium", "slow", "veryslow")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub preset: Option<String>,
    /// Video profile (e.g., "baseline", "main", "high", "main10")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub profile: Option<String>,
    /// Video level (e.g., "3.1", "4.0", "5.1")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<String>,
    /// GOP size (keyframe interval)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gop_size: Option<i32>,
    /// B-frames count
    #[serde(skip_serializing_if = "Option::is_none")]
    pub b_frames: Option<i32>,
    /// Audio codec (e.g., "aac", "mp3", "copy")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_codec: Option<String>,
    /// Audio bitrate in kbps
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_bitrate: Option<i32>,
    /// Audio sample rate in Hz
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_sample_rate: Option<i32>,
    /// Audio channels count
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_channels: Option<i32>,
    /// Container format (e.g., "mp4", "mkv", "avi")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub format: Option<String>,
    /// Color space (e.g., "bt709", "bt2020nc")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub colorspace: Option<String>,
    /// Color primaries (e.g., "bt709", "bt2020")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub color_primaries: Option<String>,
    /// Transfer characteristics (e.g., "bt709", "smpte2084")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub color_trc: Option<String>,
    /// Pixel format (e.g., "yuv420p", "yuv420p10le")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub pixel_format: Option<String>,
    /// Hardware acceleration method (e.g., "cuda", "opencl", "qsv")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hwaccel: Option<String>,
    /// GPU device index for hardware acceleration
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gpu_device: Option<String>,
    /// Two-pass encoding
    #[serde(skip_serializing_if = "Option::is_none")]
    pub two_pass: Option<bool>,
    /// Custom FFmpeg parameters
    #[serde(skip_serializing_if = "Option::is_none")]
    pub custom_params: Option<Vec<String>>,

    // NVENC-specific parameters
    /// NVENC tune setting (e.g., "hq", "ll", "ull", "lossless")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub nvenc_tune: Option<String>,
    /// Rate control mode (e.g., "constqp", "vbr", "cbr", "vbr_hq")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rate_control: Option<String>,
    /// Quantization parameter for constant QP mode (0-51)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub qp: Option<i32>,
    /// Rate control lookahead frames
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rc_lookahead: Option<i32>,
    /// Spatial adaptive quantization (0=disabled, 1=enabled)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub spatial_aq: Option<i32>,
    /// AQ strength (1-15, higher = more aggressive)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub aq_strength: Option<i32>,

    // Scaling and filtering parameters
    /// Software scaling flags for libswscale
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sws_flags: Option<String>,

    // Frame rate and timing parameters
    /// Frame rate mode (e.g., "passthrough", "cfr", "vfr")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fps_mode: Option<String>,

    // MP4 container specific parameters
    /// MP4 movflags for fragmentation and metadata
    #[serde(skip_serializing_if = "Option::is_none")]
    pub movflags: Option<String>,

    // Input/Output timing parameters
    /// Start time offset in seconds
    #[serde(skip_serializing_if = "Option::is_none")]
    pub start_time: Option<f64>,
    /// Duration limit in seconds
    #[serde(skip_serializing_if = "Option::is_none")]
    pub duration: Option<f64>,

    // Stream mapping and metadata
    /// Whether to copy metadata from input
    #[serde(skip_serializing_if = "Option::is_none")]
    pub copy_metadata: Option<bool>,
    /// Whether to disable audio output
    #[serde(skip_serializing_if = "Option::is_none")]
    pub no_audio: Option<bool>,
    /// Whether to hide FFmpeg banner
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_banner: Option<bool>,

    // Filter complex and enhancement parameters
    /// Complex filter graph for video processing
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filter_complex: Option<String>,
    /// Custom metadata to add to output
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<Vec<(String, String)>>,

    // TVAI-specific enhancement parameters
    /// TVAI enhancement model (e.g., "prob-4", "gaia-1", "artemis-1")
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_model: Option<String>,
    /// TVAI scale factor (0 = auto)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_scale: Option<i32>,
    /// TVAI target width
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_width: Option<i32>,
    /// TVAI target height
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_height: Option<i32>,
    /// TVAI preblur setting
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_preblur: Option<i32>,
    /// TVAI noise reduction
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_noise: Option<i32>,
    /// TVAI detail enhancement
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_details: Option<i32>,
    /// TVAI halo reduction
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_halo: Option<i32>,
    /// TVAI blur reduction
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_blur: Option<i32>,
    /// TVAI compression artifact reduction
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_compression: Option<i32>,
    /// TVAI estimation setting
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_estimate: Option<i32>,
    /// TVAI blend factor
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_blend: Option<f64>,
    /// TVAI device selection (-2 = auto, -1 = CPU, 0+ = GPU index)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_device: Option<i32>,
    /// TVAI VRAM usage (0 = low, 1 = high)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_vram: Option<i32>,
    /// TVAI instances count
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tvai_instances: Option<i32>,
}

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

impl Template {
    /// Load template from JSON string
    pub fn from_json(json: &str) -> Result<Self, TvaiError> {
        serde_json::from_str(json).map_err(TvaiError::JsonParseError)
    }

    /// Load template from file
    pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self, TvaiError> {
        let content = std::fs::read_to_string(path)?;
        Self::from_json(&content)
    }

    /// Convert template to JSON string
    pub fn to_json(&self) -> Result<String, TvaiError> {
        serde_json::to_string_pretty(self).map_err(TvaiError::JsonSerializeError)
    }

    /// Save template to file
    pub fn save_to_file<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), TvaiError> {
        let json = self.to_json()?;
        std::fs::write(path, json)?;
        Ok(())
    }

    /// Validate and complete template structure with default values
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate required fields
        if self.name.is_empty() {
            return Err(TvaiError::ValidationError("Template name cannot be empty".to_string()));
        }

        // Set default values for missing optional fields
        if self.author.is_empty() {
            self.author = "Unknown".to_string();
        }

        if self.date.is_empty() {
            self.date = chrono::Utc::now().format("%a %b %d %H:%M:%S %Y GMT%z").to_string();
        }

        if self.veai_version.is_empty() {
            self.veai_version = "5.1.2".to_string();
        }

        // Validate and complete settings
        self.settings.validate_and_complete()?;

        Ok(())
    }

    /// Check if template is valid
    pub fn is_valid(&self) -> bool {
        !self.name.is_empty() && self.settings.is_valid()
    }
}

impl TemplateSettings {
    /// Validate and complete template settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate and complete stabilize settings
        self.stabilize.validate_and_complete()?;

        // Validate and complete motion blur settings
        self.motion_blur.validate_and_complete()?;

        // Validate and complete slow motion settings
        self.slow_motion.validate_and_complete()?;

        // Validate and complete enhance settings
        self.enhance.validate_and_complete()?;

        // Validate and complete grain settings
        self.grain.validate_and_complete()?;

        // Validate and complete output settings
        self.output.validate_and_complete()?;

        // Validate and complete filter manager settings if present
        if let Some(ref mut fm) = self.filter_manager {
            fm.validate_and_complete()?;
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        self.stabilize.is_valid() &&
        self.motion_blur.is_valid() &&
        self.slow_motion.is_valid() &&
        self.enhance.is_valid() &&
        self.grain.is_valid() &&
        self.output.is_valid()
    }

    /// Create default template settings
    pub fn default() -> Self {
        Self {
            stabilize: StabilizeSettings::default(),
            motion_blur: MotionBlurSettings::default(),
            slow_motion: SlowMotionSettings::default(),
            enhance: EnhanceSettings::default(),
            grain: GrainSettings::default(),
            output: OutputSettings::default(),
            filter_manager: None,
        }
    }
}

impl StabilizeSettings {
    /// Validate and complete stabilize settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate smooth range
        if self.smooth < 0 || self.smooth > 100 {
            self.smooth = self.smooth.clamp(0, 100);
        }

        // Validate method
        if self.method < 0 || self.method > 1 {
            self.method = 1; // Default to full frame
        }

        // Validate reduce motion iteration
        if self.reduce_motion_iteration < 1 {
            self.reduce_motion_iteration = 2;
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        self.smooth >= 0 && self.smooth <= 100 &&
        (self.method == 0 || self.method == 1) &&
        self.reduce_motion_iteration >= 1
    }
}

impl Default for StabilizeSettings {
    fn default() -> Self {
        Self {
            active: false,
            smooth: 50,
            method: 1,
            rsc: false,
            reduce_motion: false,
            reduce_motion_iteration: 2,
        }
    }
}

impl MotionBlurSettings {
    /// Validate and complete motion blur settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Set default model if empty
        if self.model.is_empty() {
            self.model = "thm-2".to_string();
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        !self.model.is_empty()
    }
}

impl Default for MotionBlurSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: "thm-2".to_string(),
        }
    }
}

impl SlowMotionSettings {
    /// Validate and complete slow motion settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate model when active
        if self.active && self.model.is_empty() {
            self.model = "apo-8".to_string();
        }

        // Validate factor range
        if self.factor <= 0.0 {
            self.factor = 1.0;
        }

        // Validate duplicate threshold
        if self.duplicate_threshold < 0 {
            self.duplicate_threshold = 10;
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        (!self.active || !self.model.is_empty()) &&
        self.factor > 0.0 &&
        self.duplicate_threshold >= 0
    }
}

impl Default for SlowMotionSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: "apo-8".to_string(),
            factor: 1.0,
            duplicate: true,
            duplicate_threshold: 10,
        }
    }
}

impl EnhanceSettings {
    /// Validate and complete enhance settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate model when active
        if self.active && self.model.is_empty() {
            self.model = "prob-4".to_string();
        }

        // Validate video type
        if self.video_type < 0 || self.video_type > 2 {
            self.video_type = 1; // Default to progressive
        }

        // Validate field order
        if self.field_order < 0 || self.field_order > 2 {
            self.field_order = 0; // Default to auto
        }

        // Validate parameter ranges (-100 to 100 typically)
        self.compress = self.compress.clamp(-100, 100);
        self.detail = self.detail.clamp(-100, 100);
        self.sharpen = self.sharpen.clamp(-100, 100);
        self.denoise = self.denoise.clamp(-100, 100);
        self.dehalo = self.dehalo.clamp(-100, 100);
        self.deblur = self.deblur.clamp(-100, 100);
        self.add_noise = self.add_noise.clamp(-100, 100);

        // Validate recover original detail value
        self.recover_original_detail_value = self.recover_original_detail_value.clamp(0, 100);

        // Set default focus fix level if None
        if self.focus_fix_level.is_none() {
            self.focus_fix_level = Some("Off".to_string());
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        (!self.active || !self.model.is_empty()) &&
        self.video_type >= 0 && self.video_type <= 2 &&
        self.field_order >= 0 && self.field_order <= 2
    }
}

impl Default for EnhanceSettings {
    fn default() -> Self {
        Self {
            active: false,
            model: "prob-4".to_string(),
            video_type: 1,
            auto: 0,
            field_order: 0,
            compress: 0,
            detail: 0,
            sharpen: 0,
            denoise: 0,
            dehalo: 0,
            deblur: 0,
            add_noise: 0,
            recover_original_detail_value: 20,
            is_artemis: false,
            is_gaia: false,
            is_theia: false,
            is_proteus: true,
            is_iris: false,
            focus_fix_level: Some("Off".to_string()),
            is_second_enhancement: Some(false),
        }
    }
}

impl GrainSettings {
    /// Validate and complete grain settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate grain amount
        if self.grain < 0 || self.grain > 100 {
            self.grain = self.grain.clamp(0, 100);
        }

        // Validate grain size
        if self.grain_size < 1 || self.grain_size > 10 {
            self.grain_size = self.grain_size.clamp(1, 10);
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        self.grain >= 0 && self.grain <= 100 &&
        self.grain_size >= 1 && self.grain_size <= 10
    }
}

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

impl OutputSettings {
    /// Validate and complete output settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate output size method
        if self.out_size_method < 0 || self.out_size_method > 10 {
            self.out_size_method = 0; // Default to original size
        }

        // Validate output PAR
        if self.output_par < 0 {
            self.output_par = 0; // Default to auto
        }

        // Validate output FPS
        if self.out_fps < 0.0 {
            self.out_fps = 0.0; // Default to original FPS
        }

        // Set default values for optional fields
        if self.custom_resolution_priority.is_none() {
            self.custom_resolution_priority = Some(0);
        }

        if self.lock_aspect_ratio.is_none() {
            self.lock_aspect_ratio = Some(true);
        }

        // Validate extended parameters
        if let Some(width) = self.width {
            if width <= 0 || width > 16384 {
                return Err(TvaiError::ValidationError(format!("Invalid width: {}", width)));
            }
        }

        if let Some(height) = self.height {
            if height <= 0 || height > 16384 {
                return Err(TvaiError::ValidationError(format!("Invalid height: {}", height)));
            }
        }

        if let Some(bitrate) = self.bitrate {
            if bitrate <= 0 || bitrate > 100000 {
                return Err(TvaiError::ValidationError(format!("Invalid bitrate: {}", bitrate)));
            }
        }

        if let Some(crf) = self.crf {
            if crf < 0 || crf > 51 {
                self.crf = Some(crf.clamp(0, 51));
            }
        }

        if let Some(gop_size) = self.gop_size {
            if gop_size <= 0 {
                self.gop_size = Some(30); // Default GOP size
            }
        }

        if let Some(b_frames) = self.b_frames {
            if b_frames < 0 || b_frames > 16 {
                self.b_frames = Some(b_frames.clamp(0, 16));
            }
        }

        if let Some(audio_bitrate) = self.audio_bitrate {
            // Allow 0 bitrate for lossless codecs like FLAC
            let is_lossless = self.audio_codec.as_ref()
                .map(|codec| codec == "flac" || codec == "alac" || codec == "pcm_s16le")
                .unwrap_or(false);

            if !is_lossless && (audio_bitrate <= 0 || audio_bitrate > 1024) {
                return Err(TvaiError::ValidationError(format!("Invalid audio bitrate: {}", audio_bitrate)));
            } else if is_lossless && audio_bitrate < 0 {
                return Err(TvaiError::ValidationError(format!("Invalid audio bitrate: {}", audio_bitrate)));
            }
        }

        if let Some(audio_channels) = self.audio_channels {
            if audio_channels <= 0 || audio_channels > 8 {
                self.audio_channels = Some(audio_channels.clamp(1, 8));
            }
        }

        // Set default codec if not specified
        if self.codec.is_none() {
            self.codec = Some("libx264".to_string());
        }

        // Set default audio codec if not specified
        if self.audio_codec.is_none() {
            self.audio_codec = Some("aac".to_string());
        }

        // Validate NVENC parameters
        if let Some(qp) = self.qp {
            if qp < 0 || qp > 51 {
                self.qp = Some(qp.clamp(0, 51));
            }
        }

        if let Some(rc_lookahead) = self.rc_lookahead {
            if rc_lookahead < 0 || rc_lookahead > 32 {
                self.rc_lookahead = Some(rc_lookahead.clamp(0, 32));
            }
        }

        if let Some(spatial_aq) = self.spatial_aq {
            if spatial_aq < 0 || spatial_aq > 1 {
                self.spatial_aq = Some(spatial_aq.clamp(0, 1));
            }
        }

        if let Some(aq_strength) = self.aq_strength {
            if aq_strength < 1 || aq_strength > 15 {
                self.aq_strength = Some(aq_strength.clamp(1, 15));
            }
        }

        // Validate timing parameters
        if let Some(start_time) = self.start_time {
            if start_time < 0.0 {
                self.start_time = Some(0.0);
            }
        }

        if let Some(duration) = self.duration {
            if duration <= 0.0 {
                return Err(TvaiError::ValidationError(format!("Invalid duration: {}", duration)));
            }
        }

        // Set default values for new optional fields
        if self.nvenc_tune.is_none() {
            self.nvenc_tune = Some("hq".to_string());
        }

        if self.rate_control.is_none() {
            self.rate_control = Some("constqp".to_string());
        }

        if self.sws_flags.is_none() {
            self.sws_flags = Some("spline+accurate_rnd+full_chroma_int".to_string());
        }

        if self.fps_mode.is_none() {
            self.fps_mode = Some("passthrough".to_string());
        }

        if self.movflags.is_none() {
            self.movflags = Some("frag_keyframe+empty_moov+delay_moov+use_metadata_tags+write_colr".to_string());
        }

        if self.copy_metadata.is_none() {
            self.copy_metadata = Some(true);
        }

        if self.no_audio.is_none() {
            self.no_audio = Some(false);
        }

        if self.hide_banner.is_none() {
            self.hide_banner = Some(true);
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        // Basic validation
        if self.out_size_method < 0 || self.out_size_method > 10 ||
           self.output_par < 0 ||
           self.out_fps < 0.0 {
            return false;
        }

        // Extended validation
        if let Some(width) = self.width {
            if width <= 0 || width > 16384 {
                return false;
            }
        }

        if let Some(height) = self.height {
            if height <= 0 || height > 16384 {
                return false;
            }
        }

        if let Some(crf) = self.crf {
            if crf < 0 || crf > 51 {
                return false;
            }
        }

        true
    }
}

impl Default for OutputSettings {
    fn default() -> Self {
        Self {
            active: true,
            out_size_method: 0,
            crop_to_fit: false,
            output_par: 0,
            out_fps: 0.0,
            custom_resolution_priority: Some(0),
            lock_aspect_ratio: Some(true),

            // Extended parameters with sensible defaults
            width: None,
            height: None,
            codec: Some("libx264".to_string()),
            bitrate: None,
            crf: Some(23), // Balanced quality
            preset: Some("medium".to_string()),
            profile: None,
            level: None,
            gop_size: Some(30),
            b_frames: Some(3),
            audio_codec: Some("aac".to_string()),
            audio_bitrate: Some(128), // 128 kbps
            audio_sample_rate: Some(48000), // 48 kHz
            audio_channels: Some(2), // Stereo
            format: Some("mp4".to_string()),
            colorspace: None,
            color_primaries: None,
            color_trc: None,
            pixel_format: Some("yuv420p".to_string()),
            hwaccel: None,
            gpu_device: None,
            two_pass: Some(false),
            custom_params: None,

            // NVENC defaults
            nvenc_tune: Some("hq".to_string()),
            rate_control: Some("constqp".to_string()),
            qp: Some(18),
            rc_lookahead: Some(20),
            spatial_aq: Some(1),
            aq_strength: Some(15),

            // Scaling defaults
            sws_flags: Some("spline+accurate_rnd+full_chroma_int".to_string()),

            // Frame rate defaults
            fps_mode: Some("passthrough".to_string()),

            // MP4 defaults
            movflags: Some("frag_keyframe+empty_moov+delay_moov+use_metadata_tags+write_colr".to_string()),

            // Timing defaults
            start_time: None,
            duration: None,

            // Metadata and audio defaults
            copy_metadata: Some(true),
            no_audio: Some(false),
            hide_banner: Some(true),
        }
    }
}

impl FilterManagerSettings {
    /// Validate and complete filter manager settings
    pub fn validate_and_complete(&mut self) -> Result<(), TvaiError> {
        // Validate intermediate resolution
        if self.second_enhancement_intermediate_resolution < 0 || self.second_enhancement_intermediate_resolution > 10 {
            self.second_enhancement_intermediate_resolution = 3;
        }

        Ok(())
    }

    /// Check if settings are valid
    pub fn is_valid(&self) -> bool {
        self.second_enhancement_intermediate_resolution >= 0 && self.second_enhancement_intermediate_resolution <= 10
    }
}

impl Default for FilterManagerSettings {
    fn default() -> Self {
        Self {
            second_enhancement_enabled: false,
            second_enhancement_intermediate_resolution: 3,
        }
    }
}
