package com.glodon.estate.jrzhj.lhlt.service.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpUtil;
import com.glodon.estate.jrzhj.lhlt.service.common.pojo.Export2WordDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.Units;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.usermodel.*;
import org.jetbrains.annotations.NotNull;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;


/**
 * Word文档工具类
 * 用于生成带有页眉和内容的Word文档
 * 此版本用poi编写, 基本可用,但是轮兼容性还是不如末班引擎.
 *
 * @author chengzhengbo
 * @date 2025/03/22 13:59
 */
@Slf4j
public class WordUtilV2 {

    /**
     * 字体样式
     */
    private static final class FontStyle {
        static final String SONGTI = "宋体";
        static final int HEADER_TITLE_SIZE_36 = 36;
        static final int HEADER_TEXT_SIZE_24 = 28;
        static final int HEADER_TEXT_SIZE_20 = 24;
    }

    /**
     * 生成Word文档
     *
     * @param dto  数据
     * @param file 输出file
     * @throws Exception 处理异常
     */
    public static void toWord(Export2WordDTO dto, File file) throws Exception {
        // 创建文档
        XWPFDocument doc = new XWPFDocument();

        clearTable(doc);

        // 设置页眉
        addHeader(doc, dto);

        // 添加文档内容
        addDocumentContent(doc, dto);

        // 保存文档
        try (FileOutputStream out = new FileOutputStream(file)) {
            doc.write(out);
        }
    }

    private static void clearTable(XWPFDocument doc) {
        // 清理文档起始处可能存在的默认段落
        while (!doc.getParagraphs().isEmpty()) {
            doc.removeBodyElement(0);
        }

        // 清理文档起始处可能存在的默认表格
        List<XWPFTable> tables = doc.getTables();
        while (!tables.isEmpty()) {
            doc.removeBodyElement(doc.getPosOfTable(tables.get(0)));
            tables = doc.getTables();
        }
    }

    /**
     * 添加页眉
     */
    private static void addHeader(XWPFDocument doc, Export2WordDTO dto) {
        // 设置页面边距,确保页眉有足够空间显示
        CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
        CTPageMar pageMar = sectPr.addNewPgMar();
        pageMar.setTop(BigInteger.valueOf(1440)); // 上边距 1 英寸
        pageMar.setRight(BigInteger.valueOf(1440)); // 右边距 1 英寸
        pageMar.setBottom(BigInteger.valueOf(1440)); // 下边距 1 英寸
        pageMar.setLeft(BigInteger.valueOf(1440)); // 左边距 1 英寸
        pageMar.setHeader(BigInteger.valueOf(1440)); // 页眉距离 0.5 英寸
        
        // 创建页眉
        XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT);

        // 添加页眉标题
        if (dto.getHeaderTitle() != null) {
            XWPFParagraph titlePara = header.createParagraph();
            titlePara.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun titleRun = titlePara.createRun();
            titleRun.setText(dto.getHeaderTitle());
            titleRun.setFontFamily(FontStyle.SONGTI);
            // POI中字号是Word中的一半
            titleRun.setFontSize(FontStyle.HEADER_TITLE_SIZE_36 / 2); 
            titleRun.setBold(true);
        }

        // 添加页眉文本
        if (dto.getHeaderText() != null) {
            XWPFParagraph textPara = header.createParagraph();
            XWPFRun textRun = textPara.createRun();
            textRun.setText(dto.getHeaderText());
            textRun.setFontFamily(FontStyle.SONGTI);
            textRun.setFontSize(FontStyle.HEADER_TEXT_SIZE_20 / 2);

            // 添加制表符
            textPara.setAlignment(ParagraphAlignment.LEFT);
            CTTabs tabs = textPara.getCTP().getPPr().addNewTabs();
            CTTabStop tabStop = tabs.addNewTab();
            tabStop.setVal(STTabJc.RIGHT);
            tabStop.setPos(BigInteger.valueOf(9000));

            // 添加页码
            textRun = textPara.createRun();
            textRun.addTab();
            textRun.setText("第");
            textRun.setFontFamily(FontStyle.SONGTI);
            textRun.setFontSize(FontStyle.HEADER_TEXT_SIZE_20 / 2);

            // 插入页码域
            textRun.getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
            textRun = textPara.createRun();
            textRun.setText(" PAGE ");
            textRun.getCTR().addNewFldChar().setFldCharType(STFldCharType.END);

            textRun = textPara.createRun();
            textRun.setText("页");
            textRun.setFontFamily(FontStyle.SONGTI);
            textRun.setFontSize(FontStyle.HEADER_TEXT_SIZE_20 / 2);
        }
    }

    /**
     * 添加文档内容
     */
    private static void addDocumentContent(XWPFDocument doc, Export2WordDTO dto) throws Exception {
        // 创建表格
        XWPFTable table = doc.createTable();
        setTableStyle(table);
        table.removeRow(0);

        // 添加前3行并合并单元格
        addTableRow(table, dto.getRow1(), true);
        addTableRow(table, dto.getRow2(), true);
        addTableRow(table, dto.getRow3(), true);

        // 添加中间5行
        addTableRow(table, dto.getRow4(), false);
        addTableRow(table, dto.getRow5(), false);
        addTableRow(table, dto.getRow6(), false);
        addTableRow(table, dto.getRow7(), false);
        addTableRow(table, dto.getRow8(), false);
        
        // 添加检查情况标题行
        addTitleRow(table, dto.getRow9());

        // 添加检查综述
        addSectionTitle(table, dto.getRow10());
        addEmptyRow(table);

        // 添加安全问题
        addSectionTitle(table, dto.getRow11());
        addProblemContent(table, dto.getAqjcDataList());

        // 添加质量问题
        addSectionTitle(table, dto.getRow12());
        addProblemContent(table, dto.getZljcDataList());
    }

    /**
     * 设置表格样式
     */
    private static void setTableStyle(XWPFTable table) {
        // 设置表格宽度
        table.setWidth("100%");
        
        // 设置表格边框
        table.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");
        table.setTopBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");
        table.setLeftBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");
        table.setRightBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");
        table.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");
        table.setInsideVBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "auto");

        // 设置表格与上下文的间距为 0
        CTTblPr tableProperties = table.getCTTbl().getTblPr() == null ? table.getCTTbl().getTblPr() : table.getCTTbl().addNewTblPr();
        if (!tableProperties.isSetTblCellMar()) {
            tableProperties.addNewTblCellMar();
        }
        CTTblCellMar tblCellMar = tableProperties.getTblCellMar();
        if (tblCellMar.getTop() == null) {
            tblCellMar.addNewTop();
        }
        tblCellMar.getTop().setW(BigInteger.ZERO);
    }

    /**
     * 添加表格行
     */
    private static void addTableRow(XWPFTable table, String[] rowData, boolean merge) {
        XWPFTableRow row = getXwpfTableRow(table, rowData);
        // 合并单元格
        if (merge) {
            mergeCells(row, 1);
        }
    }

    private static XWPFTableRow getXwpfTableRow(XWPFTable table) {
        return getXwpfTableRow(table, new String[]{"", "", "", ""});
    }
    @NotNull
    private static XWPFTableRow getXwpfTableRow(XWPFTable table, String[] rowData) {
        XWPFTableRow row = table.createRow();
        setParagraph(row, rowData[0], 0, true);
        setParagraph(row, rowData[1], 1, false);
        setParagraph(row, rowData[2], 2, true);
        setParagraph(row, rowData[3], 3, false);
        row.setHeight(500);
        return row;
    }
    @NotNull
    private static XWPFTableRow getXwpfTableRowNotBold(XWPFTable table, String[] rowData) {
        XWPFTableRow row = table.createRow();
        setParagraph(row, rowData[0], 0, false);
        setParagraph(row, rowData[1], 1, false);
        setParagraph(row, rowData[2], 2, false);
        setParagraph(row, rowData[3], 3, false);
        row.setHeight(500); 
        return row;
    }

    private static void setParagraph(XWPFTableRow row, String text, int i, boolean blod) {
        XWPFTableCell cell = row.getCell(i);
        if (cell == null) {
            cell = row.createCell();
        }
        cell.setWidth(getWidth(i));
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        // 去除段落的前后间距
        paragraph.setSpacingBefore(0);
        paragraph.setSpacingAfter(0);
        // 设置段落的缩进为 0
        paragraph.setIndentationLeft(0);
        paragraph.setIndentationRight(0);
        XWPFRun run = paragraph.createRun();
        run.setText(text);
        run.setBold(blod);
    }

    private static String getWidth(int i) {
        switch (i) {
            case 0:
            case 2:
                return "1100";
            case 1:
                return "4400";
            case 3:
            default:
                return "2200";
        }
    }

    /**
     * 合并单元格
     */
    private static void mergeCells(XWPFTableRow row, int fromCell) {
        int size = row.getTableICells().size();
        if (size <= 1) {
            return;
        }
        for (int i = fromCell; i <= 3; i++) {
            XWPFTableCell cell = row.getCell(i);
            CTTcPr tcPr = cell.getCTTc().getTcPr();
            if (tcPr == null) {tcPr = cell.getCTTc().addNewTcPr();}
            CTHMerge hMerge = tcPr.addNewHMerge();
            if (i == fromCell) {
                hMerge.setVal(STMerge.RESTART);
            } else {
                hMerge.setVal(STMerge.CONTINUE);
            }
        }
    }

    /**
     * 添加标题行
     */
    private static void addTitleRow(XWPFTable table, String[] rowData) {
        XWPFTableRow row = getXwpfTableRow(table, rowData);
        mergeCells(row, 0);

        // 设置标题样式
        XWPFTableCell cell = row.getCell(0);
        XWPFParagraph para = cell.getParagraphs().get(0);
        XWPFRun run = para.createRun();
        run.setFontFamily(FontStyle.SONGTI);
        run.setFontSize(FontStyle.HEADER_TEXT_SIZE_24 / 2);
        run.setBold(true);
        // 设置居中对齐
        para.setAlignment(ParagraphAlignment.CENTER);
    }

    /**
     * 添加章节标题
     */
    private static void addSectionTitle(XWPFTable table, String[] rowData) {
        XWPFTableRow row = getXwpfTableRow(table, rowData);
        mergeCells(row, 0);
        // 设置样式
        XWPFTableCell cell = row.getCell(0);
        XWPFParagraph para = cell.getParagraphs().get(0);
        XWPFRun run = para.createRun();
        run.setFontFamily(FontStyle.SONGTI);
        run.setFontSize(FontStyle.HEADER_TEXT_SIZE_20 / 2);
        run.setBold(true);
        XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0);
        paragraph.setAlignment(ParagraphAlignment.LEFT);
    }

    /**
     * 添加空行
     */
    private static void addEmptyRow(XWPFTable table) {
        XWPFTableRow row = getXwpfTableRow(table);
        mergeCells(row, 0);
        // 设置最小高度
        row.setHeight(2500);
    }

    /**
     * 添加问题内容
     */
    private static void addProblemContent(XWPFTable table, List<Export2WordDTO.ProblemData> problemList) throws Exception {
        if (CollUtil.isEmpty(problemList)) {
            addEmptyRow(table);
            return;
        }

        for (Export2WordDTO.ProblemData problem : problemList.stream().filter(item -> CollUtil.isNotEmpty(item.getContext())).collect(Collectors.toList())) {
            if (problem.isImg()) {
                addImageRow(table, problem.getContext());
            } else {
                addTextRow(table, problem.getContext());
            }
        }
    }

    /**
     * 添加图片行
     */
    private static void addImageRow(XWPFTable table, List<String> imageUrls) throws Exception {
        XWPFTableRow row = getXwpfTableRow(table);
        mergeCells(row, 0);
        XWPFTableCell cell = row.getCell(0);
        while (!cell.getParagraphs().isEmpty()) {
            cell.removeParagraph(0);
        }

        // 创建两列布局的段落
        XWPFParagraph para = cell.addParagraph();
        para.setAlignment(ParagraphAlignment.LEFT);
        XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0);
        // 去除段落的前后间距
        paragraph.setSpacingBefore(0);
        paragraph.setSpacingAfter(0);
        // 设置段落的缩进为 0
        paragraph.setIndentationLeft(0);
        paragraph.setIndentationRight(0);
        
        // 添加图片
        for (int i = 0; i < Math.min(2, imageUrls.size()); i++) {
            XWPFRun run = para.createRun();
            byte[] imageData = downloadAndProcessImage(imageUrls.get(i));
            if (imageData.length > 0) {
                run.addPicture(
                    new ByteArrayInputStream(imageData),
                    getPictureType(imageUrls.get(i)),
                    imageUrls.get(i),
                    Units.toEMU(Units.pixelToPoints(285)),
                    Units.toEMU(Units.pixelToPoints(240))
                );
                // 如果不是最后一张图片,添加适当的间距
                if (i < Math.min(2, imageUrls.size()) - 1) {
                    run.setText(" ");
                }
            }
        }
    }
    /**
     * 添加文本行
     */
    private static void addTextRow(XWPFTable table, List<String> textList) {
        XWPFTableRow row = getXwpfTableRowNotBold(table, new String[]{"","","",""});
        mergeCells(row, 0);
        XWPFTableCell cell = row.getCell(0);
        cell.removeParagraph(0);
        // 添加文本内容
        for (String text : textList) {
            // 创建新的段落
            XWPFParagraph paragraph = cell.addParagraph();
            paragraph.setAlignment(ParagraphAlignment.LEFT);
            XWPFRun run = paragraph.createRun();
            run.setFontFamily(FontStyle.SONGTI);
            run.setFontSize(FontStyle.HEADER_TEXT_SIZE_20 / 2);
            run.setText(text);
            
            // 设置段落属性
            CTPPr pPr = paragraph.getCTP().getPPr();
            if (pPr == null) {
                pPr = paragraph.getCTP().addNewPPr();
            }
            CTSpacing spacing = pPr.isSetSpacing() ? pPr.getSpacing() : pPr.addNewSpacing();
            spacing.setBefore(BigInteger.ZERO);
            spacing.setAfter(BigInteger.ZERO);
        }
    }

    /**
     * 下载并处理图片
     */
    private static byte[] downloadAndProcessImage(String imageUrl) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            HttpUtil.download(imageUrl, outputStream, true);
            return outputStream.toByteArray();
        } catch (Exception e) {
            log.error("下载图片失败: {}", e.getMessage());
            return new byte[0];
        }
    }

    /**
     * 获取图片类型
     */
    private static int getPictureType(String imageUrl) {
        if (imageUrl.toLowerCase().endsWith(".png")) {
            return Document.PICTURE_TYPE_PNG;
        } else if (imageUrl.toLowerCase().endsWith(".jpg") || imageUrl.toLowerCase().endsWith(".jpeg")) {
            return Document.PICTURE_TYPE_JPEG;
        } else {
            return Document.PICTURE_TYPE_JPEG; // 默认使用JPEG
        }
    }
}

下一篇