//! Frame interpolation implementation

use std::path::Path;
use std::time::Instant;
use crate::core::{TvaiError, TvaiProcessor, ProcessResult, ProgressCallback};
use crate::video::InterpolationParams;

/// Frame interpolation implementation
impl TvaiProcessor {
    /// Interpolate video frames to create smooth slow motion
    pub async fn interpolate_video(
        &mut self,
        input_path: &Path,
        output_path: &Path,
        params: InterpolationParams,
        progress_callback: Option<&ProgressCallback>,
    ) -> Result<ProcessResult, TvaiError> {
        let start_time = Instant::now();

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

        // Validate parameters
        self.validate_interpolation_params(&params)?;

        let operation_id = self.generate_operation_id();

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

        // Calculate target FPS
        let target_fps = match params.target_fps {
            Some(fps) => fps,
            None => (params.input_fps as f32 * params.multiplier) as u32,
        };

        // Build Topaz interpolation filter
        let interpolation_filter = self.build_interpolation_filter(&params, target_fps)?;

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

        // Build FFmpeg command with Topaz interpolation filter
        let mut args = vec![
            "-y", "-hide_banner", "-nostdin", "-strict", "2",
            "-hwaccel", "auto",
            "-i", input_path.to_str().unwrap(),
            "-vf", &interpolation_filter,
        ];

        // Add encoding settings (use high quality for interpolation)
        if self.is_gpu_enabled() {
            args.extend_from_slice(&[
                "-c:v", "hevc_nvenc",
                "-preset", "slow",
                "-global_quality", "17",
                "-pix_fmt", "yuv420p",
            ]);
        } else {
            args.extend_from_slice(&[
                "-c:v", "libx264",
                "-preset", "slow",
                "-crf", "17",
            ]);
        }

        args.push(output_path.to_str().unwrap());

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

        // Execute Topaz interpolation (requires Topaz FFmpeg)
        self.execute_ffmpeg_command(&args, true, progress_callback).await?;

        let processing_time = start_time.elapsed();

        // Get FFmpeg version for metadata
        let ffmpeg_version = self.get_ffmpeg_version(true).await.ok();

        // Create result metadata
        let mut metadata = self.create_metadata(
            operation_id,
            input_path,
            format!("interpolation: model={}, input_fps={}, multiplier={}, target_fps={}",
                params.model.as_str(),
                params.input_fps,
                params.multiplier,
                target_fps
            ),
        );
        metadata.ffmpeg_version = ffmpeg_version;

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

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

    /// Validate interpolation parameters
    fn validate_interpolation_params(&self, params: &InterpolationParams) -> Result<(), TvaiError> {
        if params.input_fps == 0 {
            return Err(TvaiError::InvalidParameter(
                "Input FPS must be greater than 0".to_string()
            ));
        }

        if params.multiplier < 1.0 || params.multiplier > 8.0 {
            return Err(TvaiError::InvalidParameter(
                format!("Multiplier must be between 1.0 and 8.0, got {}", params.multiplier)
            ));
        }

        if let Some(target_fps) = params.target_fps {
            if target_fps == 0 {
                return Err(TvaiError::InvalidParameter(
                    "Target FPS must be greater than 0".to_string()
                ));
            }

            if target_fps > 240 {
                return Err(TvaiError::InvalidParameter(
                    format!("Target FPS too high: {} (max 240)", target_fps)
                ));
            }
        }

        Ok(())
    }

    /// Build Topaz interpolation filter string
    fn build_interpolation_filter(&self, params: &InterpolationParams, target_fps: u32) -> Result<String, TvaiError> {
        let filter = format!(
            "tvai_fi=model={}:fps={}",
            params.model.as_str(),
            target_fps
        );

        Ok(filter)
    }
}
