package vip.xiaonuo.disk.util;

import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class OfficeConverter {


    private final String minioEndpoint;
    private final String accessKey;
    private final String secretKey;
    private final String bucketName;
    private final MinioClient minioClient;

    @Autowired
    public OfficeConverter(
            @Value("${ufop.minio.endpoint}") String minioEndpoint,
            @Value("${ufop.minio.access-key}") String accessKey,
            @Value("${ufop.minio.secret-key}") String secretKey,
            @Value("${ufop.minio.bucket-name}") String bucketName
    ) {
        this.minioEndpoint = minioEndpoint;
        this.accessKey = accessKey;
        this.secretKey = secretKey;
        this.bucketName = bucketName;
        this.minioClient = MinioClient.builder()
                .endpoint(minioEndpoint)
                .credentials(accessKey, secretKey)
                .build();
    }

    private static final String LIBRE_OFFICE_PATH = "soffice"; // Linux路径

    public void main(String[] args) {
        try {
            convertAndUpload("upload/20241010/fba210e119de04088439e64b062665da.doc", "665da.docx");
//            convertAndUpload("netdisk", "upload/20240705/7faa77badef7a854e3bf664a2ddb1a4f.ppt", "netdisk", "b1a4f.pptx");
//            convertAndUpload("netdisk", "upload/20250611/答辩会议室号.xls", "netdisk", "室号.xlsx");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void convertAndUpload(String inputFile, String outputFile) throws Exception {
        // 1. 从MinIO下载文件
        File tempInput = downloadFromMinio(bucketName, inputFile);

        // 2. 执行LibreOffice转换
        File tempOutput = convertWithLibreOffice(tempInput, getOutputFormat(outputFile));

        // 3. 上传到MinIO
        uploadToMinio(bucketName, outputFile, tempOutput);

        // 4. 清理临时文件
        deleteFiles(tempInput, tempOutput);
    }

    private File downloadFromMinio(String bucket, String objectName) throws Exception {
        // 使用UUID确保唯一性
        String uniqueId = UUID.randomUUID().toString();
        Path tempDir = Files.createTempDirectory("minio-download-");
        Path tempPath = tempDir.resolve(uniqueId + ".tmp");

        try {
            minioClient.downloadObject(
                    DownloadObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .filename(tempPath.toString())
                            .build());
            return tempPath.toFile();
        } catch (Exception e) {
            // 清理失败的文件
            Files.deleteIfExists(tempPath);
            Files.deleteIfExists(tempDir);
            throw e;
        }
    }

    private File convertWithLibreOffice(File inputFile, String outputFormat) throws Exception {
        File outputFile = File.createTempFile("converted-", "." + outputFormat);

        ProcessBuilder pb = new ProcessBuilder(
                LIBRE_OFFICE_PATH,
                "--headless",
                "--convert-to", outputFormat,
                "--outdir", outputFile.getParent(),
                inputFile.getAbsolutePath());

        Process process = pb.start();

        // 等待转换完成（最长等待120秒）
        if (!process.waitFor(120, TimeUnit.SECONDS)) {
            process.destroyForcibly();
            throw new RuntimeException("LibreOffice转换超时");
        }

        if (process.exitValue() != 0) {
            throw new RuntimeException("LibreOffice转换失败，退出码: " + process.exitValue());
        }

        // 查找生成的文件（LibreOffice可能生成不同名称的文件）
        File convertedFile = new File(outputFile.getParent(),
                inputFile.getName().replaceAll("\\.\\w+$", "." + outputFormat));

        if (!convertedFile.exists()) {
            throw new FileNotFoundException("未找到转换后的文件: " + convertedFile.getAbsolutePath());
        }

        return convertedFile;
    }

//    private void uploadToMinio(String bucket, String objectName, File file) throws Exception {
//        minioClient.uploadObject(
//                UploadObjectArgs.builder()
//                        .bucket(bucketName)
//                        .object(objectName)
//                        .filename("/convert")
//                        .contentType(getMimeType(objectName))
//                        .build());
//    }

    private void uploadToMinio(String bucket, String objectName, File file) throws Exception {
        minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object("converted/"+objectName)
                        .filename(file.getAbsolutePath())
                        .contentType(getMimeType(objectName))
                        .build());
    }

    private  void deleteFiles(File... files) {
        for (File f : files) {
            if (f != null && f.exists()) {
                f.delete();
            }
        }
    }

    private  String getOutputFormat(String outputFile) {
        if (outputFile.endsWith(".docx")) {
            return "docx";
        }
        if (outputFile.endsWith(".pptx")) {
            return "pptx";
        }
        if (outputFile.endsWith(".xlsx")) {
            return "xlsx";
        }
        throw new IllegalArgumentException("不支持的输出格式: " + outputFile);
    }

    private String getMimeType(String fileName) {
        return switch (fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase()) {
            case "docx" -> "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "pptx" -> "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            case "xlsx" -> "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            default -> "application/octet-stream";
        };
    }

}
