package com.casic.missiles.service.listeners.register;


import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.casic.missiles.dto.business.certificate.ElectronicImage;
import com.casic.missiles.dto.business.file.CropPicture;
import com.casic.missiles.dto.business.file.FilePrintRegister;
import com.casic.missiles.service.listeners.util.ParseWord07;
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.fields.TextRange;
import liquibase.pro.packaged.E;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author：zt
 * @Create：2023/3/7/9:30
 * @Description：TODO Word文件操作工具类
 * @Version：1.0
 */

public class FilePrintRegisterUtils {

    //关键字索引 (-1)
    private final static Integer keyWordIndex = -1;
    //照片透明度设置
    private final static int alpha = 150;


    /**
     * @param filePrintRegister 证书文件注册
     */
    public static String filePrintGenerate(FilePrintRegister filePrintRegister) throws RuntimeException {
        //1、按照模板填充数据,并导出word，执行填充行数之后，再进行页数的填充
        String wordOldUrl = exportWord(filePrintRegister.getTemplatePath(), filePrintRegister.getTemDir(), filePrintRegister.getFileName(), filePrintRegister.getParams());
//        Document document = new Document();
//        document.loadFromFile(wordOldUrl);
//        document.getPageCount();
        //设置透明属性  1、获取照片 2、签章背景透明设置 3、设置照片路径和照片类型进行图片保存
//        for (ElectronicImage electronicSeal : filePrintRegister.getElectronicImageList()) {
//            BufferedImage bi = readImage(electronicSeal.getElectronicSealImageUrl());
//            BufferedImage electronSealImage = convertLayout(bi, electronicSeal.getDiaphaneity());
//            String stampImgUrl = electronicSeal.getElectronicSealImageUrl();
//            String imagePath = stampImgUrl.substring(0, stampImgUrl.length() - 4) + "1.png";
//            String[] imageCutOffContents = stampImgUrl.split(".");
//            electronicSeal.setElectronicSealImageUrl(imagePath);
//            saveFile(electronSealImage, imageCutOffContents[imageCutOffContents.length - 1], imagePath);
//        }
        // 初始化world，pdf名称参数
        String wordNewUrl = filePrintRegister.getTemplatePath();
        //默认转为docx，只需要进行docx的替换即可
        String pdfNewUrl = filePrintRegister.getTemplatePath().replaceAll("docx", "pdf");

        if (CollectionUtils.isNotEmpty(filePrintRegister.getElectronicImageList())) {
            //按关键字进行分组
            Map<String, List<ElectronicImage>> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream()
                    .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord()))
                    .collect(
                            Collectors.groupingBy(ElectronicImage::getKeyWord)
                    );
            //3、根据关键字进行添加签章和签字
            for (Map.Entry<String, List<ElectronicImage>> entry : sameKeyWordSealMaps.entrySet()) {
                List<ElectronicImage> electronicSeals = entry.getValue();
                addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSeals);
            }
            //获取没有关键字的图片，即绝对路径的图片
            List<ElectronicImage> absolutePathImageList = filePrintRegister.getElectronicImageList().stream()
                    .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord()))
                    .collect(Collectors.toList());
            //根据设置的绝对路径进行图片的填充
            for (ElectronicImage absolutePathImage : absolutePathImageList) {
                addAbsolutePathStamp(wordOldUrl, wordNewUrl, absolutePathImage);
            }
            //由于合成word总页数存在不准确，先转换为pdf进行获取合成证书总页数, 处理齐缝章
        }
        // 4、将新word转化为pdf文件
        wordToPdf(wordNewUrl, pdfNewUrl);
        return pdfNewUrl;
    }


    /**
     * 将相同关键字的印章添加到同一个位置进行打印
     * 1、根据关键词位置添加电子印章
     * 2、替换书签名位置文本内容 bookmarkName传参为null，则不进行书签替换操作
     *
     * @param wordOldUrl         word文件路径
     * @param wordNewUrl         新word文件路径
     * @param electronicSealList 电子印章信息
     */
    private static void addSameKeyWordStamp(String wordOldUrl, String
            wordNewUrl, List<ElectronicImage> electronicSealList) throws RuntimeException {
        if (CollectionUtils.isEmpty(electronicSealList)) {
            return;
        }
        // 加载文档
        Document document = new Document();
        document.loadFromFile(wordOldUrl);
        //获取关键字位置
        TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false);
        for (ElectronicImage electronicSeal : electronicSealList) {
            //加签章照片
            if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) {
                throw new RuntimeException("image url is empty  or key word not exist in the word template ...");
            }
            //多处关键字添加同一个签章
            for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) {
                Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph();
                textSelections[keyWordIndex].getCount();

                //添加公司印章
                DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl());
                //设置图片位于文字顶层
                docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text);
                //指定电子章位置
                //水平位置
                docPicture.setHorizontalPosition(electronicSeal.getHorizontal());
                //垂直位置
                docPicture.setVerticalPosition(electronicSeal.getVertical());
                //设置电子章大小
                docPicture.setWidth(electronicSeal.getStampWidth());
                docPicture.setHeight(electronicSeal.getStampHeight());
            }
        }

        //保存添加电子章的Word文档
        document.saveToFile(wordNewUrl);
        document.dispose();
    }

    /**
     * 替换书签名位置文本内容
     *
     * @param document        word文档对象
     * @param bookmarkName    书签名
     * @param newBookmarkText 新文本内容
     */
    private static void replaceBookmarkContent(Document document, String bookmarkName, String newBookmarkText) {
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document);
        bookmarksNavigator.moveToBookmark(bookmarkName);
        //用文本内容替换原有书签位置的文本，新替换的内容与原文格式一致
        bookmarksNavigator.replaceBookmarkContent(newBookmarkText, true);
    }

    /**
     * word转PDF
     *
     * @param wordNewUrl word文件路径
     * @param pdfNewUrl  存储新PDF文件路径
     */
    public static void wordToPdf(String wordNewUrl, String pdfNewUrl) {
//        将新Word文档转换为PDF文件
        Document document = new Document();
        document.loadFromFile(wordNewUrl);
        document.saveToFile(pdfNewUrl, FileFormat.PDF);
        document.dispose();
    }

    /**
     * 图片透明背景转换
     *
     * @param imgsrc
     * @param alpha
     * @return
     */
    public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) {
        try {
            //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行，存储为jpg，底色为黑色
            BufferedImage back = new BufferedImage(imgsrc.getWidth(), imgsrc.getHeight(), BufferedImage.TYPE_INT_ARGB);
            int width = imgsrc.getWidth();
            int height = imgsrc.getHeight();
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
                    int rgb = imgsrc.getRGB(i, j);
                    Color color = new Color(rgb);
                    Color newcolor = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
                    back.setRGB(i, j, newcolor.getRGB());
                }
            }
            return back;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //读取图片
    private static BufferedImage readImage(String imgpath) {
        try {
            BufferedImage bufferedImage = ImageIO.read(new File(imgpath));
            return bufferedImage;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //保存图片,extent为格式，"jpg"、"png"等
    private static void saveFile(BufferedImage img, String extent, String newfile) {
        try {
            ImageIO.write(img, extent, new File(newfile));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 1、自定义位置添加电子印章
     * 2、替换书签名位置文本内容 bookmarkName传参为null，则不进行书签替换操作
     *
     * @param wordOldUrl word文件路径
     * @param wordNewUrl 新word文件路径
     */
    private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) {
        //        加载文档
        Document document = new Document();
        document.loadFromFile(wordOldUrl);
        //获取指定段落
        Section section = document.getSections().get(0);
        //log.info("获取文档内容段落总数{}",count);
        Paragraph paragraph = section.getParagraphs().get(0);
        //        判断是否需要替换书签位置文本内容
        if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) {
            replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText());
        }
//        添加电子印章
        DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl());

//        指定电子章位置
//        水平位置
        docPicture.setHorizontalPosition(absolutePathImage.getHorizontal());
//        垂直位置
        docPicture.setVerticalPosition(absolutePathImage.getVertical());

//        设置电子章大小
        docPicture.setWidth(absolutePathImage.getStampWidth());
        docPicture.setHeight(absolutePathImage.getStampHeight());

//        设置图片位于文字顶层
        docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text);
        //        保存添加电子章的Word文档
        document.saveToFile(wordNewUrl);
        document.dispose();
//      log.info("文档添加电子印章结束，新WORD文档地址：{}",wordNewUrl);
    }


    /**
     * 替换书签名位置文本内容为图片
     *
     * @param document     word文档对象
     * @param bookmarkName 书签名
     * @param newImgUrl    图片地址
     */
    public void replaceBookmarkContentToImg(Document document, String bookmarkName, String newImgUrl) {
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document);
        bookmarksNavigator.moveToBookmark(bookmarkName);
        //添加图片，替换原有书签内容
        Paragraph para = new Paragraph(document);
        para.appendPicture(newImgUrl);
        TextBodyPart bodyPart = new TextBodyPart(document);
        bodyPart.getBodyItems().add(para);
        bookmarksNavigator.replaceBookmarkContent(bodyPart);
    }

    /**
     * 替换书签名位置文本内容为表格
     *
     * @param document     word文档对象
     * @param bookmarkName 书签名
     */
    public void replaceBookmarkContentToTable(Document document, String bookmarkName) {
        //声明数组内容
        String[][] data =
                {
                        new String[]{"分类", "等级", "编号"},
                        new String[]{"A", "一级", "01A"},
                        new String[]{"B", "二级", "02B"},
                        new String[]{"C", "三级", "03C"},
                };

        //创建表格
        Table table = new Table(document, true);
        table.resetCells(4, 3);
        for (int i = 0; i < data.length; i++) {
            TableRow dataRow = table.getRows().get(i);
            for (int j = 0; j < data[i].length; j++) {
                TextRange range = dataRow.getCells().get(j).addParagraph().appendText(data[i][j]);
                range.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                range.getCharacterFormat().setFontName("楷体");
                dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center);
                dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            }
        }

        //创建TextBodyPart对象
        TextBodyPart bodyPart = new TextBodyPart(document);
        bodyPart.getBodyItems().add(table);

        //定位到指定书签位置
        BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document);
        bookmarkNavigator.moveToBookmark(bookmarkName);

        //使用表格替换原书签的内容
        bookmarkNavigator.replaceBookmarkContent(bodyPart);
    }

    /**
     * 文件转流
     *
     * @param wordNewUrl
     * @return
     */
    public byte[] getBytesByFile(String wordNewUrl) {
        try {
//            byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl));
            File file = new File(wordNewUrl);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = fis.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            fis.close();
            bos.close();
            byte[] bytes = bos.toByteArray();
            System.out.println("successful...");
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * doc 转 docx
     *
     * @param sourceFilePath 源文件路径
     * @param destFilePath   转换成docx文件路径
     */
    public static void docToDocx(String sourceFilePath, String destFilePath) {
        Document document = new Document();
        document.loadFromFile(sourceFilePath);
        document.saveToFile(destFilePath);
    }

    /**
     * 流转文件
     *
     * @param buf      流字节数组
     * @param filePath 新文件路径
     * @param fileName 新文件名称
     */
    public static void byteToFile(byte[] buf, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 按照模板 填充数据生成word  只支持docx
     *
     * @param templatePath 模板文件路径
     * @param temDir       生成文件的目录
     * @param fileName     生成文件名
     * @param params       参数
     */
    public static String exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params) {
        Assert.notNull(templatePath, "模板路径不能为空");
        Assert.notNull(temDir, "临时文件路径不能为空");
        Assert.notNull(fileName, "导出文件名不能为空");
        if (fileName.endsWith(".doc")) {
            docToDocx(templatePath, templatePath + "x");
            templatePath += "x";
        }
        Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式");
        File dir = new File(temDir);
        if (!dir.getParentFile().exists()) {
            // 新建文件夹
            dir.getParentFile().mkdirs();
        }
        String tmpPath = "";
        try {
            ParseWord07 parseWord07=new ParseWord07();
            XWPFDocument doc = parseWord07.parseWord(templatePath, params);
            tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tmpPath;
    }



    public static void main(String[] args) throws RuntimeException {
        String pathUrl = "D:\\casic";
        String localPathUrl = "D:\\casic\\";
        // 目标文件地址
        String wordOldUrl = pathUrl + "\\工作记录单.docx";
        // 添加电子印章后文件存放地址
        String wordNewUrl = localPathUrl + "\\tem1.docx";
        Map<String, Object> params = new HashMap<>();
        List<Map<String, String>> assetList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Map<String, String> assetMap = new HashMap<>();
            assetMap.put("assetName", "我不是设备名称");
            assetMap.put("model", "我不是型号");
            assetMap.put("assetNo", "我是设备编号");
            assetList.add(assetMap);
        }
        params.put("assetList", assetList);
        params.put("logNo", "本编号");
        params.put("laboratoryName", "此去半生");
        params.put("executiveAddress", "猜猜我在哪里");
        exportWord(wordOldUrl, localPathUrl, "temp.docx", params);


//        //WORD转PDF存放位置
//        String pdfNewUrl = localPathUrl + "\\tem.pdf";
//        //电子印章图片地址
//        String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png";
//        //电子签名图片地址
//        String stampSealImgUrl = localPathUrl + "\\ceshi.jpg";
//        // word文档内容关键字
//        FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils();
//        List<ElectronicImage> electronicSealList = new ArrayList(11);
//        ElectronicImage electronicImage = defaultElectronicSignName("批准人");
//        electronicImage.setElectronicSealImageUrl(stampNameImgUr);
//        electronicSealList.add(electronicImage);
//        addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList);
//        //加载文档
//        Document document = new Document();
//        document.loadFromFile(wordOldUrl);
//        //获取段落总数
//        int count = document.getPageCount();
//        System.out.println(count);
//        String[] imageCutOffContents = stampSealImgUrl.split("\\.");
//        CropPicture cropPicture = CropPicture.builder()
//                .targetImgUrl(stampSealImgUrl)
//                .cutCols(count)
//                .cutRows(1)
//                .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2])
//                .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1])
//                .build();
//        try {
//            ImageTool.crosswiseCutting(cropPicture);
//        } catch (IOException ex) {
//
//        }
////        将新word转化为pdf文件
////        addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl);
    }

    protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) {
        ElectronicImage electronicImage = ElectronicImage.builder()
                .keyWordIndex(-1)
                .keyWord(keyWord)
                .vertical(-50f)
                .horizontal(450f)
                .stampHeight(100f)
                .stampWidth(100f)
                .diaphaneity(150f)
                .build();
        return electronicImage;
    }

    protected static ElectronicImage defaultElectronicSignName(String keyWord) {
        ElectronicImage electronicImage = ElectronicImage.builder()
                .keyWordIndex(-1)
                .keyWord(keyWord)
                .vertical(-10f)
                .horizontal(60f)
                .stampHeight(40f)
                .stampWidth(60f)
                .diaphaneity(150f)
                .build();
        return electronicImage;
    }

}