package org.dromara.system.api.utils;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author lilemy
 * @date 2025/4/17 14:53
 */
public class DocumentUtil {

    /**
     * 在给定的 run 里插入图片，并按原始大小（或缩放后大小）设置宽高。
     *
     * @param run        要插入图片的 XWPFRun
     * @param imagePath  本地图片路径或 URL（这里示例用本地文件）
     * @param document   当前文档对象
     * @param maxWidthPx 最大允许宽度（像素），如果原图更宽就按比例缩放；设置为 <=0 则不缩放
     */
    public static void insertImageDynamic(XWPFRun run,
                                          String imagePath,
                                          XWPFDocument document,
                                          int maxWidthPx) throws Exception {
        // 1. 先把图片读到 byte[]
        byte[] imgBytes = Files.readAllBytes(Paths.get(imagePath));
        // 2. 用 ImageIO 读出宽高（像素）
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));
        int widthPx = img.getWidth();
        int heightPx = img.getHeight();
        // 3. 如果指定了最大宽度，而且原图更宽，则按比例缩放
        if (maxWidthPx > 0 && widthPx > maxWidthPx) {
            double ratio = (double) maxWidthPx / widthPx;
            widthPx = maxWidthPx;
            heightPx = (int) (heightPx * ratio);
        }
        // 4. 把像素转换成 EMU
        int widthEmu = Units.pixelToEMU(widthPx);
        int heightEmu = Units.pixelToEMU(heightPx);
        // 5. 插入图片
        String lower = imagePath.toLowerCase();
        int format = lower.endsWith(".png") ? XWPFDocument.PICTURE_TYPE_PNG
            : lower.endsWith(".gif") ? XWPFDocument.PICTURE_TYPE_GIF
            : lower.endsWith(".jpeg") ? XWPFDocument.PICTURE_TYPE_JPEG
            : lower.endsWith(".jpg") ? XWPFDocument.PICTURE_TYPE_JPEG
            : XWPFDocument.PICTURE_TYPE_PNG; // 默认当 PNG
        try (InputStream picIn = new ByteArrayInputStream(imgBytes)) {
            run.addPicture(picIn, format, imagePath, widthEmu, heightEmu);
        }
    }


    /**
     * 递归将 sourceDir 中的所有文件和子目录，按照相对于 rootDir 的路径写入 ZipOutputStream。
     *
     * @param rootDir   源目录的根，用来计算相对路径
     * @param sourceDir 当前递归到的目录
     * @param zos       ZIP 输出流
     */
    public static void zipDirectory(Path rootDir, Path sourceDir, ZipOutputStream zos) throws IOException {
        // 遍历当前目录下的所有文件和文件夹
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
            for (Path entry : stream) {
                if (Files.isDirectory(entry)) {
                    // 如果是目录，递归
                    zipDirectory(rootDir, entry, zos);
                } else {
                    // 如果是文件，创建一个 ZipEntry，路径以 '/' 分隔
                    Path relativePath = rootDir.relativize(entry);
                    String zipEntryName = relativePath.toString().replace(File.separatorChar, '/');
                    ZipEntry zipEntry = new ZipEntry(zipEntryName);
                    zos.putNextEntry(zipEntry);
                    // 把文件内容写入 ZIP
                    try (InputStream is = Files.newInputStream(entry)) {
                        byte[] buffer = new byte[4096];
                        int len;
                        while ((len = is.read(buffer)) != -1) {
                            zos.write(buffer, 0, len);
                        }
                    }
                    zos.closeEntry();
                }
            }
        }
    }

}
