use std::process::Command;

/// Command-line tools
///
/// ```plain
/// Command::new(program)：创建一个新的命令对象，program 是要执行的命令名称或路径
/// .arg(arg)：添加命令参数
/// .args(args)：添加多个命令参数（接收迭代器）
/// .output()：执行命令并捕获输出（stdout/stderr）和退出状态
/// .status()：执行命令并仅获取退出状态（输出直接传递给父进程）
/// .spawn()：启动命令但不等待其完成（返回 Child 结构体，可手动控制）
/// .env(key, value)：设置环境变量
/// .current_dir(path)：设置命令执行的工作目录
/// ```
pub struct CmdUtil;

impl CmdUtil {

    /// 运行命令
    ///
    /// cmd: 数组方式的命令，第一个元素是命名执行程序
    ///
    /// ```rust
    /// use mitoo::CmdUtil;
    ///
    /// CmdUtil::run_cmd(vec!["ffmpeg", "-i", "input.mp4", "output.mp4"])
    /// ```
    pub fn run_cmd(cmd: Vec<&str>) -> Result<String, String> {
        if cmd.len() > 0 {
            let full_command_line = cmd.join(" ").to_string();
            let mut c = Command::new(cmd[0]);
            if cmd.len() > 1 {
                c.args(&cmd[1..]);
            }
            // 执行命令并捕获输出
            let output = c.output().expect("请检查命令是否正确，或是否具备执行权限或环境变量等！");
            // 处理命令执行结果
            if output.status.success() {
                println!("命令执行成功: \n{}", full_command_line);
                // 可选：打印ffmpeg输出信息
                let stdout = String::from_utf8_lossy(&output.stdout);
                println!("命令输出:\n{}", stdout);
                return Ok(stdout.to_string());
            } else {
                println!("命令执行失败: \n{}", full_command_line);
                // 打印错误信息
                let stderr = String::from_utf8_lossy(&output.stderr);
                println!("错误信息:\n{}", stderr);
                return Ok(stderr.to_string());
            }
        }
        Err("没有命令".to_string())
    }

    /// TODO 未测试过
    pub fn run_script(script_path: &str) -> std::io::Result<()> {
        #[cfg(windows)]
        let status = Command::new("cmd.exe")
            .arg("/c")
            .arg(script_path)  // Windows 批处理脚本路径
            .status()?;
    
        #[cfg(not(windows))]
        let status = Command::new("/bin/sh")
            .arg(script_path)  // Unix Shell 脚本路径
            .status()?;
    
        println!("脚本执行状态: {}", status);
        Ok(())
    }

    /// TODO 未测试过
    pub fn run_script_with_params(script_path: &str, params: Vec<&str>) -> std::io::Result<()> {
        #[cfg(windows)]
        let status = Command::new("cmd.exe")
            .arg("/c")
            .arg(script_path)  // Windows 批处理脚本路径
            .args(&params)
            .status()?;
    
        #[cfg(not(windows))]
        let status = Command::new("/bin/sh")
            .arg(script_path)  // Unix Shell 脚本路径
            .args(&params)
            .status()?;
    
        println!("脚本执行状态: {}", status);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_run_cmd() {
        // 在 Windows 上使用 cmd.exe 执行 cd 命令
        // let result = Command::new("cmd.exe")
        //     .arg("/c")
        //     .arg("cd /d D:/Environment && dir")  // 可以追加其他命令查看效果
        //     .status()
        //     .expect("执行命令失败");

        let cmd = vec!["cmd.exe", "/c", "cd", "/d", "d:/Environment/"];
        let res = CmdUtil::run_cmd(cmd);
        println!("{:?}", res);

        let cmd = vec!["ffmpeg"];
        let res = CmdUtil::run_cmd(cmd);
        println!("{:?}", res);
    }
}