package com.fs.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class VideoUtil {

    /** 与项目 AudioUtils 等模块一致：优先 C:\ffmpeg.exe，其次 PATH 中的 ffmpeg */
    private static String resolveFfmpegCommand() {
        String winPath = "C:\\ffmpeg.exe";
        if (new File(winPath).exists()) {
            return winPath;
        }
        String envPath = System.getenv("FFMPEG_PATH");
        if (envPath != null && !envPath.isEmpty() && new File(envPath).exists()) {
            return envPath;
        }
        return "ffmpeg";
    }

    /**
     * 获取视频元信息（宽高、大小、时长等）
     */
    public static Map<String, Object> getVideoInfo(File videoFile) throws IOException, InterruptedException {
        Map<String, Object> videoInfo = new HashMap<>();
        String videoPath = videoFile.getAbsolutePath();
        String[] command = {
                resolveFfmpegCommand(),
                "-i", videoPath
        };

        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.trim().startsWith("Duration:")) {
                    String durationStr = line.split(",")[0].replace("Duration:","").trim();
                    videoInfo.put("duration", parseDurationToSeconds(durationStr));
                }
                if (line.contains("Video:") && line.contains("fps")) {
                    String[] parts = line.split(",");
                    for (String part : parts) {
                        Pattern pattern = Pattern.compile("(\\d{2,5})x(\\d{2,5})");
                        Matcher matcher = pattern.matcher(part.trim());
                        if (matcher.find()) {
                            videoInfo.put("width", Integer.parseInt(matcher.group(1)));
                            videoInfo.put("height", Integer.parseInt(matcher.group(2)));
                            break;
                        }
                    }
                }
            }
        }

        int exitCode = process.waitFor();
        if (exitCode != 0 && exitCode != 1) {
            throw new RuntimeException("FFmpeg 获取视频信息失败，退出代码：" + exitCode);
        }

        videoInfo.put("size", videoFile.length());

        return videoInfo;
    }

    /**
     * 将时长字符串转换为秒
     */
    public static Integer parseDurationToSeconds(String durationStr) {
        String[] parts = durationStr.split(":");
        int hours = (int) Math.round(Double.parseDouble(parts[0]));
        int minutes = (int) Math.round(Double.parseDouble(parts[1]));
        int seconds = (int) Math.round(Double.parseDouble(parts[2]));
        return hours * 3600 + minutes * 60 + seconds;
    }

    /**
     * 提取缩略图
     */
    public static void extractFirstFrame(String videoPath, String outputImagePath) throws IOException, InterruptedException {
        String[] command = {
                resolveFfmpegCommand(),
                "-ss", "00:00:01.000",  // 精准定位到第1秒
                "-i", videoPath,        // 输入视频路径
                "-vframes", "1",        // 只提取1帧
                "-q:v", "2",            // 质量控制（2=高质量，范围1-31）
                "-y",                   // 覆盖输出文件
                outputImagePath         // 输出图片路径（如 cover.jpg）
        };
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true); // 将标准错误和标准输出合并
        Process process = processBuilder.start();
//        process.waitFor();

        // 处理进程的标准输出和错误流
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                log.info(line); // 输出到控制台或日志
            }
        }

        int exitCode = process.waitFor();
        if (exitCode != 0 && exitCode != 1) {
            throw new RuntimeException("FFmpeg 执行失败，退出代码：" + exitCode);
        }
    }
}
