package com.datamate.datamanagement.application;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * LibreOffice 文档转换工具
 */
public final class LibreOfficeConverter {
    private static final String LIBREOFFICE_COMMAND = "soffice";
    private static final Duration CONVERT_TIMEOUT = Duration.ofMinutes(5);
    private static final int MAX_OUTPUT_LENGTH = 500;

    private LibreOfficeConverter() {
    }

    public static void convertToPdf(Path sourcePath, Path targetPath) throws Exception {
        Path outputDir = targetPath.getParent();
        List<String> command = List.of(
            LIBREOFFICE_COMMAND,
            "--headless",
            "--nologo",
            "--nolockcheck",
            "--nodefault",
            "--nofirststartwizard",
            "--convert-to",
            "pdf",
            "--outdir",
            outputDir.toString(),
            sourcePath.toString()
        );
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        boolean finished = process.waitFor(CONVERT_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
        String output = readProcessOutput(process.getInputStream());
        if (!finished) {
            process.destroyForcibly();
            throw new IllegalStateException("LibreOffice 转换超时");
        }
        if (process.exitValue() != 0) {
            throw new IllegalStateException("LibreOffice 转换失败: " + output);
        }
        Path generated = outputDir.resolve(stripExtension(sourcePath.getFileName().toString()) + ".pdf");
        if (!Files.exists(generated)) {
            throw new IllegalStateException("LibreOffice 输出文件不存在");
        }
        if (!generated.equals(targetPath)) {
            Files.move(generated, targetPath, StandardCopyOption.REPLACE_EXISTING);
        }
    }

    private static String readProcessOutput(InputStream inputStream) throws IOException {
        if (inputStream == null) {
            return "";
        }
        byte[] buffer = new byte[1024];
        StringBuilder builder = new StringBuilder();
        int total = 0;
        int read;
        while ((read = inputStream.read(buffer)) >= 0) {
            if (read == 0) {
                continue;
            }
            int remaining = MAX_OUTPUT_LENGTH - total;
            if (remaining <= 0) {
                break;
            }
            int toAppend = Math.min(remaining, read);
            builder.append(new String(buffer, 0, toAppend, StandardCharsets.UTF_8));
            total += toAppend;
            if (total >= MAX_OUTPUT_LENGTH) {
                break;
            }
        }
        return builder.toString();
    }

    private static String stripExtension(String fileName) {
        if (fileName == null || fileName.isBlank()) {
            return "preview";
        }
        int dotIndex = fileName.lastIndexOf('.');
        return dotIndex <= 0 ? fileName : fileName.substring(0, dotIndex);
    }
}
