package com.zksy.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.PdfSaveOptions;
import com.aspose.words.SaveFormat;
import com.deepoove.poi.XWPFTemplate;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordUtils {
    /*
     * @Description:
     * @Param:
     * @param inputPath word文件路径
     * @param keysToCheck 需要校验的键
     * @return:
     **/
    public static void checkKeys(String inputPath, Set<String> keysToCheck) {
        XWPFDocument document;
        try (FileInputStream fis = new FileInputStream(inputPath)) {
            document = new XWPFDocument(fis);
        } catch (IOException e) {
            throw new RuntimeException("读取模板文件失败: " + e.getMessage());
        }
        // 查找模板中的所有占位符
        Set<String> placeholders = findPlaceholders(document);
        // 校验模板中是否包含所有替换变量！
        for (String key : keysToCheck) {
            if (!placeholders.contains(key)) {
                throw new RuntimeException("缺少模板占位符对应的替换内容: " + key);
            }
        }
    }

    /*
     * @Description: 插入word
     * @param inputPath 输入文件路径
     * @param outputPath 输出文件路径
     * @param hashMap 替换内容
     * @param keysToCheck 需要校验的键
     **/
    public static void insertWord(String inputPath, String outputPath, HashMap<String, Object> hashMap) {
        // 使用poi-tl模板引擎进行渲染
        XWPFTemplate template = XWPFTemplate.compile(inputPath).render(hashMap);
        try {
            // 将渲染后的模板写入输出文件
            template.writeAndClose(Files.newOutputStream(Paths.get(outputPath)));
        } catch (IOException e) {
            // 捕获异常并抛出运行时异常
            throw new RuntimeException("写入输出文件失败: " + e.getMessage());
        }
    }

    /*
     * @Description: word转pdf
     * @Param:
     * @param wordFilePath word文件路径
     * @param pdfFilePath  pdf文件路径
     * @return:
     **/
    public static void wordToPdf(String wordFilePath, String pdfFilePath) {
        FileOutputStream fileOS = null;
        try {
            Document doc = new Document(wordFilePath);
            fileOS = new FileOutputStream(pdfFilePath);

            // 保存转换的pdf文件
            doc.save(fileOS, SaveFormat.PDF);
//            addWaterMark(pdfFilePath);
        } catch (Exception e) {
            throw new RuntimeException("转换Word文档为PDF失败: " + e.getMessage());
        } finally {
            try {
                if (fileOS != null) {
                    fileOS.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭文件输出流时发生错误");
            }
        }
    }

    /*
     * @Description: word转pdf并返回File对象
     * @Param:
     * @param wordFilePath word文件路径
     * @return: java.io.File 转换后的PDF文件
     **/
    public static File wordToPdfAndGetFile(String wordFilePath) {
        FileOutputStream fileOS = null;
        try {
            Document doc = new Document(wordFilePath);

            // 创建临时PDF文件
            File pdfFile = File.createTempFile("converted_", ".pdf");
            fileOS = new FileOutputStream(pdfFile);

            // 保存转换的pdf文件
            doc.save(fileOS, SaveFormat.PDF);
            fileOS.close();

            return pdfFile;
        } catch (Exception e) {
            throw new RuntimeException("转换Word文档为PDF失败: " + e.getMessage());
        } finally {
            try {
                if (fileOS != null) {
                    fileOS.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭文件输出流时发生错误");
            }
        }
    }

    // 初始化字体目录（只执行一次）
    private static final String FONT_DIR;

    static {
        try {
            // 创建临时字体目录
            File tempFontDir = Files.createTempDirectory("fonts").toFile();
            FONT_DIR = tempFontDir.getAbsolutePath();

            // 把 resources/fonts 下的字体文件复制到临时目录
            String[] fontFiles = { "simsun.ttc", "SimSun.ttf", "msyh.ttc" };
            for (String fontFile : fontFiles) {
                ClassPathResource resource = new ClassPathResource("fonts/" + fontFile);
                if (resource.exists()) {
                    File targetFile = new File(tempFontDir, fontFile);
                    try (InputStream in = resource.getInputStream()) {
                        Files.copy(in, targetFile.toPath());
                    }
                }
            }

            // 设置 Aspose 全局字体目录
            FontSettings fontSettings = FontSettings.getDefaultInstance();
            fontSettings.setFontsFolders(new String[]{FONT_DIR}, true);

        } catch (IOException e) {
            throw new RuntimeException("初始化字体目录失败", e);
        }
    }
    /*
     * @Description: word文件转pdf文件（生成临时文件）
     * @Param:
     * @param wordFile word文件对象
     * @return: java.io.File 转换后的PDF文件
     **/
    public static File wordToPdf(File wordFile) {
        FileOutputStream fileOS = null;
        try {
            Document doc = new Document(wordFile.getAbsolutePath());

            // PDF 保存选项，嵌入字体，保证跨平台显示一致
            PdfSaveOptions saveOptions = new PdfSaveOptions();
            saveOptions.setEmbedFullFonts(true);

            // 创建临时 PDF 文件
            File pdfFile = File.createTempFile("converted_", ".pdf");
            fileOS = new FileOutputStream(pdfFile);
            doc.save(fileOS, saveOptions);
            return pdfFile;
        } catch (Exception e) {
            throw new RuntimeException("转换Word文档为PDF失败: " + e.getMessage(), e);
        } finally {
            try {
                if (fileOS != null) {
                    fileOS.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭文件输出流时发生错误");
            }
        }
    }

    public static ByteArrayOutputStream wordToPdf(InputStream wordFile, String fontFolderPath, String fontName) {
        ByteArrayOutputStream pdfFile = new ByteArrayOutputStream();
        try {
            Document doc = new Document(wordFile);
            FontSettings fontSettings = new FontSettings();
            String os = System.getProperty("os.name").toLowerCase();
            if (StrUtil.isNotBlank(os) && os.contains("win")) {
                String path = WordUtils.class.getResource(fontFolderPath + fontName).getPath();
                if (StrUtil.isNotBlank(path)) {
                    // 配置字体
                    path = path.substring(0, path.lastIndexOf("/") + 1);
                    fontSettings.setFontsFolder(path, true);
                }
            } else {
                fontSettings.setFontsFolder(fontFolderPath, true);
            }
            doc.setFontSettings(fontSettings);
            // 保存转换的pdf文件
            doc.save(pdfFile, SaveFormat.PDF);
            return pdfFile;
        } catch (Exception e) {
            throw new RuntimeException("转换Word文档为PDF失败: " + e.getMessage());
        } finally {
            try {
                pdfFile.close();
            } catch (IOException e) {
                System.out.println("关闭文件输出流时发生错误");
            }
        }
    }

    public static ByteArrayOutputStream wordToPdfWithWaterMark(InputStream wordFile, String... watermarkTexts) {
        ByteArrayOutputStream pdfFile = new ByteArrayOutputStream();
        try {
            Document doc = new Document(wordFile);
            // 保存转换的pdf文件
            doc.save(pdfFile, SaveFormat.PDF);
            return addWaterMark(pdfFile, watermarkTexts);
        } catch (Exception e) {
            throw new RuntimeException("转换Word文档为PDF失败: " + e.getMessage());
        } finally {
            try {
                pdfFile.close();
            } catch (IOException e) {
                System.out.println("关闭文件输出流时发生错误");
            }
        }
    }

    public static ByteArrayOutputStream addWaterMark(ByteArrayOutputStream pdfFile, String... watermarkTexts) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(pdfFile.toByteArray());
        ByteArrayOutputStream pdfFileWithWaterMark = new ByteArrayOutputStream();
        PdfStamper stamper = new PdfStamper(reader, pdfFileWithWaterMark);
        doAddWaterMark(reader, stamper, watermarkTexts);
        return pdfFileWithWaterMark;
    }

    private static void addWaterMark(String pdfFilePath, String... watermarkTexts) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(pdfFilePath);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("F:\\tempDocument\\temp\\result.pdf"));
        doAddWaterMark(reader, stamper, watermarkTexts);
    }

    private static void doAddWaterMark(PdfReader reader, PdfStamper stamper, String... watermarkTexts) throws DocumentException, IOException {
        if (ArrayUtil.isEmpty(watermarkTexts)) {
            watermarkTexts = new String[]{"水印"};
        }

        String fontPath = WordUtils.class.getResource("/fonts/SimSun.ttf").getPath();
        BaseFont bf = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

        PdfContentByte over;
        PdfTemplate template;
        PdfGState gs = new PdfGState();
        // 设置透明度为30%
        gs.setFillOpacity(0.3f);

        float x = 298;
        float y;
        float rotation = 45;
        // 设置每行水印之间的间隔
        float lineSpacing = 160;

        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            over = stamper.getOverContent(i);
            // 应用透明度设置
            over.setGState(gs);
            // 重置y坐标为每页的初始位置
            y = 421;

            for (String watermarkText : watermarkTexts) {
                template = over.createTemplate(500, 500);
                template.setLineWidth(0.25f);
                template.setColorStroke(BaseColor.LIGHT_GRAY);
                template.beginText();
                template.setFontAndSize(bf, 60);
                template.setColorFill(BaseColor.GRAY);
                template.showTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, x, y, rotation);
                template.endText();
                over.addTemplate(template, 0, 0);
                // 调整每行水印的垂直位置
                y -= lineSpacing;
            }
        }

        stamper.close();
        reader.close();
    }


    /*
     * @Description: 查找word中的所有占位符
     * @param document
     * @return java.util.Set<java.lang.String>
     **/
    private static Set<String> findPlaceholders(XWPFDocument document) {
        Set<String> placeholders = new HashSet<>();
        Pattern pattern = Pattern.compile("\\{\\{\\s*(@?\\w+)\\s*\\}\\}");
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            String paragraphText = paragraph.getText();
            Matcher matcher = pattern.matcher(paragraphText);
            while (matcher.find()) {
                placeholders.add(matcher.group(1).trim());
            }
        }
        return placeholders;
    }

    public static void main(String[] args) {
//        // 定义输入和输出文件的路径
//        String inputPath = "D:\\software\\Java\\projects\\word-utils\\src\\main\\java\\org\\example\\utils\\demo.docx";
        String outputPath = "C:\\Users\\hxb\\Downloads\\6357971575460482300.docx";
        String outputPdfPath = "C:\\Users\\hxb\\Downloads\\sex.pdf";
//        // 定义替换内容的键值对
//        HashMap<String, Object> hashMap = new HashMap<>();
//        // 承租方
//        hashMap.put("name", "Hi, poi-tl Word模板引擎");
//        // 房屋基本情况
//        hashMap.put("list", "2层1户、"+"2层2户、"+"2层3户");
//        // 租约起止日期
//        hashMap.put("zuFromToDate", "2022年一月一日至2023年一月一日");
//        // 押金
//        hashMap.put("zj", "5000");
//        // 押金大写
//        hashMap.put("dxzj", "伍佰");
//        // 押金
//        hashMap.put("yj", "500");
//        // 约定租金
//        hashMap.put("ydzj", "500");
//        // 调用insertWord方法来处理文档
//        HashSet<String> strings = new HashSet<>();
//        strings.add("yz1");
//        checkKeys(inputPath, strings);
//        insertWord(inputPath, outputPath, hashMap);
        // 将Word文档转换为PDF
        wordToPdf(outputPath, outputPdfPath);
    }

}
