package vip.xiaonuo.disk.util;

import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.XmlParserException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

@Component
public class VideoConverter {

    // MinIO配置

    @Value("${ufop.minio.endpoint}")
    private String MINIO_ENDPOINT;
    @Value("${ufop.minio.access-key}")
    private String ACCESS_KEY;
    @Value("${ufop.minio.secret-key}")
    private String SECRET_KEY;
    @Value("${ufop.minio.bucket-name}")
    private String BUCKET_NAME;
    @Value("${ufop.minio.FFMPEG_PATH}")
    private String FFMPEG_PATH;


    public void convertAndUpload(String inputKey, String outputPrefix, String[] formats) throws Exception {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(MINIO_ENDPOINT)
                .credentials(ACCESS_KEY, SECRET_KEY)
                .build();

        // 创建临时目录
        File tempDir = new File("temp");
        if (!tempDir.exists()) {
            tempDir.mkdir();
        }
        List<File> filesToDelete = new ArrayList<>(); // 待删除文件列表

        try {
            // 下载源文件
            File localInput = new File(tempDir, inputKey);
            downloadFromMinio(minioClient, BUCKET_NAME, inputKey, localInput);
            filesToDelete.add(localInput); // 添加到删除列表
            // 执行格式转换
            for (String format : formats) {
                File outputFile = new File(tempDir, outputPrefix + "." + format);
                convertVideo(localInput.getAbsolutePath(), outputFile.getAbsolutePath(), format);

                // 上传转换后的文件
                uploadToMinio(minioClient, BUCKET_NAME, outputFile.getName(), outputFile);
                filesToDelete.add(outputFile); // 添加到删除列表
            }
        } finally {
            // 清理临时文件（保留目录结构）
            for (File file : filesToDelete) {
                if (file.exists() && !file.delete()) {
                    System.err.println("警告：无法删除临时文件 " + file.getAbsolutePath());
                }
            }
        }
    }

//    private void convertVideo(String inputPath, String outputPath, String format) throws IOException, InterruptedException {
//        List<String> command = new ArrayList<>();
//        command.add(FFMPEG_PATH);
//        command.add("-i");
//        command.add(inputPath);
//        command.add("-c:v");
//        command.add("libx264");
//        command.add("-c:a");
//        command.add("aac");
//        command.add(outputPath);
//
//        ProcessBuilder pb = new ProcessBuilder(command);
//        pb.redirectErrorStream(true);
//        Process process = pb.start();
//
//        // 读取输出日志
//        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
//            String line;
//            while ((line = reader.readLine()) != null) {
//                System.out.println(line);
//            }
//        }
//
//        int exitCode = process.waitFor();
//        if (exitCode != 0) {
//            throw new RuntimeException("FFmpeg转换失败，退出码：" + exitCode);
//        }
//    }

    // 修改convertVideo方法以接受文件路径参数
    private void convertVideo(String inputPath, String outputPath, String format)
            throws IOException, InterruptedException {

        List<String> command = new ArrayList<>();
        command.add(FFMPEG_PATH);
        command.add("-y"); // 覆盖输出文件（避免重复转换问题）
        command.add("-i");
        command.add(inputPath);
        command.add("-c:v");
        command.add("libx264");
        command.add("-c:a");
        command.add("aac");
        command.add(outputPath);

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

        // 读取输出日志
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        }

        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new RuntimeException("FFmpeg转换失败，退出码：" + exitCode);
        }
    }

    private static void downloadFromMinio(MinioClient client, String bucket, String object, File dest) throws Exception {
        if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build())) {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
        }
        client.downloadObject(
                DownloadObjectArgs.builder()
                        .bucket(bucket)
                        .object(object)
                        .filename(dest.getAbsolutePath())
                        .build()
        );
    }

    private static void uploadToMinio(MinioClient client, String bucket, String object, File file) throws Exception {
        client.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucket)
                        .object("convert/" + object)
                        .filename(file.getAbsolutePath())
                        .contentType(getMimeType(object))
                        .build()
        );
    }

    private static String getMimeType(String fileName) {
        return switch (fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase()) {
            case "mp4" -> "video/mp4";
            case "wmv" -> "video/x-ms-wmv";
            case "avi" -> "video/avi";
            case "flv" -> "video/x-flv";
            case "mpeg" -> "video/mpeg";
            case "mpg" -> "video/mpeg";
            case "rmvb" -> "application/vnd.rn-realmedia-vbr";
            case "mov" -> "video/quicktime";
            default -> "application/octet-stream";
        };
    }

    private static void deleteDirectory(File dir) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteDirectory(f);
                } else {
                    f.delete();
                }
            }
        }
        dir.delete();
    }


    /**
     * 获取转换后的文件大小
     */
    public Long getConverterFileSize(String filePath) {
        Long size = 0L;
        // 初始化MinIO客户端（需替换您的配置）
        MinioClient minioClient = MinioClient.builder()
                .endpoint(MINIO_ENDPOINT)
                .credentials(ACCESS_KEY, SECRET_KEY)
                .build();

        try {
            // 1. 构建查询参数
            StatObjectArgs statArgs = StatObjectArgs.builder()
                    .bucket(BUCKET_NAME)
                    .object(filePath)
                    .build();

            // 2. 获取元数据
            StatObjectResponse statObjectResponse = minioClient.statObject(statArgs);

            // 3. 提取文件大小
            size = statObjectResponse.size();
            System.out.printf("文件大小: %.2f MB%n", size / (1024.0 * 1024.0));

        } catch (Exception e) {

        }
        return size;
    }




//
//    public static void convertAndUpload(String inputObjectPath, String outputPrefix, String[] formats) throws Exception {
//        MinioClient minioClient = MinioClient.builder()
//                .endpoint(MINIO_ENDPOINT)
//                .credentials(ACCESS_KEY, SECRET_KEY)
//                .build();
//
//        // 1. 从MinIO获取输入流
//        InputStream minioInputStream = minioClient.getObject(
//                GetObjectArgs.builder()
//                        .bucket(BUCKET_NAME)
//                        .object(inputObjectPath)
//                        .build()
//        );
//
//        // 2. 执行格式转换
//        for (String format : formats) {
//            // 创建FFmpeg进程
//            ProcessBuilder pb = new ProcessBuilder(FFMPEG_PATH,
//                    "-i", "pipe:0",          // 从标准输入读取
//                    "-c:v", "mpeg4",         // 示例编码器配置
//                    "-c:a", "pcm_s16le",
//                    "-f", format,            // 强制指定输出格式
//                    "pipe:1"                 // 输出到标准输出
//            );
//
//            pb.redirectErrorStream(true);
//            Process ffmpegProcess = pb.start();
//
//            // 3. 创建上传任务
//            CompletableFuture.runAsync(() -> {
//                try {
//                    // 构建MinIO上传参数
//                    PutObjectArgs putArgs = PutObjectArgs.builder()
//                            .bucket(BUCKET_NAME)
//                            .object(getOutputObjectName(inputObjectPath, format))
//                            .contentType(getMimeType(format))
//                            .build();
//
//                    // 获取可写的OutputStream（正确方式）
//                    try () {
//                        // 创建管道线程（单向传输：FFmpeg → MinIO）
//                        Thread outputThread = new Thread(() -> {
//                            try {
//                                pipeStreams(
//                                        ffmpegProcess.getInputStream(),
//                                        minioOutputStream
//                                );
//                            } catch (IOException e) {
//                                throw new RuntimeException(e);
//                            }
//                        });
//
//                        outputThread.start();
//                        outputThread.join();
//
//                        // 等待FFmpeg进程完成
//                        int exitCode = ffmpegProcess.waitFor();
//                        if (exitCode != 0) {
//                            throw new RuntimeException("FFmpeg转换失败，退出码：" + exitCode);
//                        }
//                    }
//                } catch (Exception e) {
//                    throw new RuntimeException("转换/上传过程出错", e);
//                }
//            }).join();
//        }
//    }
//
//    private static void pipeStreams(InputStream src, OutputStream dest) throws IOException {
//        byte[] buffer = new byte[8192];
//        int bytesRead;
//        while ((bytesRead = src.read(buffer)) != -1) {
//            dest.write(buffer, 0, bytesRead);
//        }
//    }
//
//    private static String getOutputObjectName(String inputPath, String format) {
//        String baseName = inputPath.substring(0, inputPath.lastIndexOf('.'));
//        return baseName + "_converted." + format;
//    }
//
//    private static String getMimeType(String format) {
//        String lowerFormat = format.toLowerCase();
//        switch (lowerFormat) {
//            case "mp4":
//                return "video/mp4";
//            case "wmv":
//                return "video/x-ms-wmv";
//            case "avi":
//                return "video/x-msvideo";
//            case "flv":
//                return "video/x-flv";
//            case "mpeg":
//            case "mpg":
//                return "video/mpeg";
//            case "rmvb":
//                return "application/vnd.rn-realmedia-vbr";
//            case "mov":
//                return "video/quicktime";
//            default:
//                return "application/octet-stream";
//        }
//    }

}
