use anyhow::{Result, anyhow};
use std::path::Path;
use std::process::Command;
use tracing::{info, debug, error};

/// FFmpeg水印处理工具类
/// 专门用于水印相关的FFmpeg操作
pub struct FFmpegWatermark;

impl FFmpegWatermark {
    /// 创建隐藏窗口的命令
    fn create_hidden_command(program: &str) -> Command {
        let mut cmd = Command::new(program);
        
        #[cfg(windows)]
        {
            use std::os::windows::process::CommandExt;
            cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW
        }
        
        cmd
    }

    /// 执行FFmpeg命令
    pub fn execute_command(args: &[&str]) -> Result<()> {
        debug!("执行FFmpeg命令: {:?}", args);
        
        let output = Self::create_hidden_command("ffmpeg")
            .args(args)
            .output()
            .map_err(|e| anyhow!("FFmpeg执行失败: {}", e))?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            error!("FFmpeg命令失败: {}", stderr);
            return Err(anyhow!("FFmpeg命令执行失败: {}", stderr));
        }

        Ok(())
    }

    /// 提取视频帧到指定时间戳
    pub fn extract_frame_at_timestamp(
        input_path: &str,
        timestamp: f64,
        output_path: &str,
        width: u32,
        height: u32,
    ) -> Result<()> {
        if !Path::new(input_path).exists() {
            return Err(anyhow!("输入文件不存在: {}", input_path));
        }

        // 确保输出目录存在
        if let Some(parent) = Path::new(output_path).parent() {
            std::fs::create_dir_all(parent)?;
        }

        let timestamp_str = timestamp.to_string();
        let scale_filter = format!("scale={}:{}", width, height);

        let args = vec![
            "-hide_banner",
            "-loglevel", "error",
            "-ss", &timestamp_str,
            "-i", input_path,
            "-vframes", "1",
            "-vf", &scale_filter,
            "-y", output_path,
        ];

        Self::execute_command(&args)?;

        // 验证输出文件是否创建成功
        if !Path::new(output_path).exists() {
            return Err(anyhow!("帧提取失败，输出文件不存在"));
        }

        info!("成功提取帧: {} -> {}", input_path, output_path);
        Ok(())
    }

    /// 获取视频信息
    pub fn get_video_info(input_path: &str) -> Result<VideoInfo> {
        if !Path::new(input_path).exists() {
            return Err(anyhow!("输入文件不存在: {}", input_path));
        }

        let output = Self::create_hidden_command("ffprobe")
            .args(&[
                "-hide_banner",
                "-loglevel", "error",
                "-select_streams", "v:0",
                "-show_entries", "stream=width,height,duration,nb_frames",
                "-of", "csv=p=0",
                input_path,
            ])
            .output()
            .map_err(|e| anyhow!("ffprobe执行失败: {}", e))?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(anyhow!("ffprobe命令失败: {}", stderr));
        }

        let stdout = String::from_utf8_lossy(&output.stdout);
        let parts: Vec<&str> = stdout.trim().split(',').collect();

        if parts.len() < 3 {
            return Err(anyhow!("无法解析视频信息"));
        }

        let width = parts[0].parse::<u32>().ok();
        let height = parts[1].parse::<u32>().ok();
        let duration = parts[2].parse::<f64>().unwrap_or(0.0);
        let frame_count = if parts.len() > 3 {
            parts[3].parse::<u32>().ok()
        } else {
            None
        };

        Ok(VideoInfo {
            width,
            height,
            duration,
            frame_count,
        })
    }

    /// 应用视频滤镜
    pub fn apply_video_filter(
        input_path: &str,
        output_path: &str,
        filter: &str,
        quality_args: &[&str],
    ) -> Result<()> {
        if !Path::new(input_path).exists() {
            return Err(anyhow!("输入文件不存在: {}", input_path));
        }

        // 确保输出目录存在
        if let Some(parent) = Path::new(output_path).parent() {
            std::fs::create_dir_all(parent)?;
        }

        let mut args = vec![
            "-hide_banner",
            "-loglevel", "error",
            "-i", input_path,
            "-vf", filter,
        ];

        // 添加质量参数
        args.extend_from_slice(quality_args);
        args.extend_from_slice(&["-c:a", "copy", "-y", output_path]);

        Self::execute_command(&args)?;

        // 验证输出文件
        if !Path::new(output_path).exists() {
            return Err(anyhow!("视频处理失败，输出文件不存在"));
        }

        info!("成功应用视频滤镜: {} -> {}", input_path, output_path);
        Ok(())
    }

    /// 应用复杂滤镜（支持多输入）
    pub fn apply_complex_filter(
        input_paths: &[&str],
        output_path: &str,
        filter_complex: &str,
        quality_args: &[&str],
    ) -> Result<()> {
        // 验证所有输入文件存在
        for input_path in input_paths {
            if !Path::new(input_path).exists() {
                return Err(anyhow!("输入文件不存在: {}", input_path));
            }
        }

        // 确保输出目录存在
        if let Some(parent) = Path::new(output_path).parent() {
            std::fs::create_dir_all(parent)?;
        }

        let mut args = vec!["-hide_banner", "-loglevel", "error"];

        // 添加所有输入文件
        for input_path in input_paths {
            args.extend_from_slice(&["-i", input_path]);
        }

        // 添加复杂滤镜
        args.extend_from_slice(&["-filter_complex", filter_complex]);

        // 添加质量参数
        args.extend_from_slice(quality_args);
        args.extend_from_slice(&["-c:a", "copy", "-y", output_path]);

        Self::execute_command(&args)?;

        // 验证输出文件
        if !Path::new(output_path).exists() {
            return Err(anyhow!("视频处理失败，输出文件不存在"));
        }

        info!("成功应用复杂滤镜: {:?} -> {}", input_paths, output_path);
        Ok(())
    }

    /// 处理图片
    pub fn process_image(
        input_path: &str,
        output_path: &str,
        filter: &str,
    ) -> Result<()> {
        if !Path::new(input_path).exists() {
            return Err(anyhow!("输入文件不存在: {}", input_path));
        }

        // 确保输出目录存在
        if let Some(parent) = Path::new(output_path).parent() {
            std::fs::create_dir_all(parent)?;
        }

        let args = vec![
            "-hide_banner",
            "-loglevel", "error",
            "-i", input_path,
            "-vf", filter,
            "-y", output_path,
        ];

        Self::execute_command(&args)?;

        // 验证输出文件
        if !Path::new(output_path).exists() {
            return Err(anyhow!("图片处理失败，输出文件不存在"));
        }

        info!("成功处理图片: {} -> {}", input_path, output_path);
        Ok(())
    }

    /// 处理带多个输入的图片（如添加水印）
    pub fn process_image_with_overlay(
        input_paths: &[&str],
        output_path: &str,
        filter_complex: &str,
    ) -> Result<()> {
        // 验证所有输入文件存在
        for input_path in input_paths {
            if !Path::new(input_path).exists() {
                return Err(anyhow!("输入文件不存在: {}", input_path));
            }
        }

        // 确保输出目录存在
        if let Some(parent) = Path::new(output_path).parent() {
            std::fs::create_dir_all(parent)?;
        }

        let mut args = vec!["-hide_banner", "-loglevel", "error"];

        // 添加所有输入文件
        for input_path in input_paths {
            args.extend_from_slice(&["-i", input_path]);
        }

        // 添加复杂滤镜
        args.extend_from_slice(&["-filter_complex", filter_complex]);
        args.extend_from_slice(&["-y", output_path]);

        Self::execute_command(&args)?;

        // 验证输出文件
        if !Path::new(output_path).exists() {
            return Err(anyhow!("图片处理失败，输出文件不存在"));
        }

        info!("成功处理图片叠加: {:?} -> {}", input_paths, output_path);
        Ok(())
    }

    /// 检查FFmpeg是否可用
    pub fn is_available() -> bool {
        Self::create_hidden_command("ffmpeg")
            .arg("-version")
            .output()
            .map(|output| output.status.success())
            .unwrap_or(false)
    }

    /// 获取FFmpeg版本信息
    pub fn get_version() -> Result<String> {
        let output = Self::create_hidden_command("ffmpeg")
            .arg("-version")
            .output()
            .map_err(|e| anyhow!("获取FFmpeg版本失败: {}", e))?;

        if !output.status.success() {
            return Err(anyhow!("FFmpeg不可用"));
        }

        let stdout = String::from_utf8_lossy(&output.stdout);
        let first_line = stdout.lines().next().unwrap_or("Unknown version");
        Ok(first_line.to_string())
    }
}

/// 视频信息结构
#[derive(Debug, Clone)]
pub struct VideoInfo {
    pub width: Option<u32>,
    pub height: Option<u32>,
    pub duration: f64,
    pub frame_count: Option<u32>,
}
