package com.qmth.distributed.print.business.util;

import com.itextpdf.awt.AsianFontMapper;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.boot.tools.models.ByteArray;
import com.qmth.distributed.print.business.bean.dto.PdfDto;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysConfig;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.PageSizeEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.util.FileUtil;
import com.qmth.teachcloud.common.util.HtmlToPdfUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;
import org.springframework.util.FileCopyUtils;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;

/**
 * @Description: 合并pdf util
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/4/7
 */
public class PdfUtil {
    private final static Logger log = LoggerFactory.getLogger(PdfUtil.class);

    /**
     * 将多个PDF合并成一个PDF
     *
     * @param files
     * @param outputPath
     * @param fileTempList
     */
    public static String mergePdf(String[] files, String outputPath, List<File> fileTempList) {
        Document document = null;
        PdfCopy copy = null;
        StringJoiner dirName = new StringJoiner("");
        File pdfFileTemp = null;
        try {
            if (Objects.nonNull(files) && files.length > 0) {
                document = new Document(new PdfReader(ByteArray.fromFile(new File(files[0])).value()).getPageSize(1));
                if (Objects.isNull(outputPath)) {
                    pdfFileTemp = SystemConstant.getFileTempVar(SystemConstant.PDF_PREFIX);
                    fileTempList.add(pdfFileTemp);
                    dirName.add(pdfFileTemp.getPath());
                    outputPath = dirName.toString();
                }
                copy = new PdfSmartCopy(document, new FileOutputStream(outputPath));
                document.open();
                for (int i = 0; i < files.length; i++) {
                    PdfReader reader = new PdfReader(ByteArray.fromFile(new File(files[i])).value());
                    int numberOfPages = reader.getNumberOfPages();
                    for (int j = 1; j <= numberOfPages; j++) {
                        document.newPage();
                        PdfImportedPage page = copy.getImportedPage(reader, j);
                        copy.addPage(page);
                    }
                    reader.close();
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(document)) {
                document.close();
            }
            if (Objects.nonNull(copy)) {
                copy.flush();
                copy.close();
            }
        }
        return Objects.nonNull(dirName) ? dirName.toString() : null;
    }

    /**
     * 将多个PDF合并成一个PDF
     *
     * @param files
     * @param outputPath
     */
    public static String mergePdf(String[] files, String outputPath) {
        Document document = null;
        PdfCopy copy = null;
        StringJoiner dirName = new StringJoiner("");
        File pdfFileTemp = null;
        try {
            if (Objects.nonNull(files) && files.length > 0) {
                document = new Document(new PdfReader(ByteArray.fromFile(new File(files[0])).value()).getPageSize(1));
                if (Objects.isNull(outputPath)) {
                    pdfFileTemp = SystemConstant.getFileTempVar(SystemConstant.PDF_PREFIX);
                    dirName.add(pdfFileTemp.getPath());
                    outputPath = dirName.toString();
                }
                copy = new PdfSmartCopy(document, new FileOutputStream(outputPath));
                document.open();
                for (int i = 0; i < files.length; i++) {
                    PdfReader reader = new PdfReader(ByteArray.fromFile(new File(files[i])).value());
                    int numberOfPages = reader.getNumberOfPages();
                    for (int j = 1; j <= numberOfPages; j++) {
                        document.newPage();
                        PdfImportedPage page = copy.getImportedPage(reader, j);
                        copy.addPage(page);
                    }
                    reader.close();
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(document)) {
                document.close();
            }
            if (Objects.nonNull(copy)) {
                copy.flush();
                copy.close();
            }
//            if(Objects.nonNull(pdfFileTemp)){
//                FileUtil.deleteFile(pdfFileTemp);
//            }
        }
        return Objects.nonNull(dirName) ? dirName.toString() : null;
    }

    /**
     * 新增空白pdf（奇数页补空白面后变成偶数页）
     *
     * @param pdfFile
     */
    public static PdfDto addPdfPage(File pdfFile) throws IOException {
        PdfReader reader = null;
        FileOutputStream fileOutputStream = null;
        int pageCount = 0;
        PageSizeEnum pageSizeEnum = null;
        try {
            if (Objects.nonNull(pdfFile)) {
                reader = new PdfReader(ByteArray.fromFile(pdfFile).value());
                pageCount = reader.getNumberOfPages();
                Rectangle rectangle = reader.getPageSize(1);
                pageSizeEnum = PageSizeEnum.convertToEnum(rectangle.getWidth(), rectangle.getHeight());
                if (Math.abs(pageCount % 2) == 1) {//取偶
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    PdfStamper stamper = new PdfStamper(reader, baos);
                    stamper.insertPage(pageCount + 1, reader.getPageSizeWithRotation(1));
                    stamper.close();
                    fileOutputStream = new FileOutputStream(pdfFile);
                    IOUtils.write(baos.toByteArray(), fileOutputStream);
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(reader)) {
                reader.close();
            }
            if (Objects.nonNull(fileOutputStream)) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }
        return new PdfDto(pageSizeEnum, Objects.nonNull(reader) ? reader.getNumberOfPages() : 0, pageCount);
    }

    /**
     * 新增pdf page
     *
     * @param pdfFile
     * @return
     * @throws IOException
     */
    public static void addPdfEmptyPage(File pdfFile) throws IOException {
        PdfReader reader = null;
        FileOutputStream fileOutputStream = null;
        int pageCount;
        try {
            if (Objects.nonNull(pdfFile)) {
                reader = new PdfReader(ByteArray.fromFile(pdfFile).value());
                pageCount = reader.getNumberOfPages();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PdfStamper stamper = new PdfStamper(reader, baos);
                for (int i = 1; i <= pageCount; i++) {
                    stamper.insertPage(2 * i, reader.getPageSizeWithRotation(1));
                }
                stamper.close();
                fileOutputStream = new FileOutputStream(pdfFile);
                IOUtils.write(baos.toByteArray(), fileOutputStream);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(reader)) {
                reader.close();
            }
            if (Objects.nonNull(fileOutputStream)) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }
    }

    /**
     * 获取pdfPages
     *
     * @param pdfFile
     * @return
     * @throws IOException
     */
    public static int getPdfPages(File pdfFile) throws IOException {
        PdfReader reader = null;
        try {
            if (Objects.nonNull(pdfFile)) {
                reader = new PdfReader(ByteArray.fromFile(pdfFile).value());
                return reader.getNumberOfPages();
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(reader)) {
                reader.close();
            }
        }
        return 0;
    }

    /**
     * 获取pdf格式
     *
     * @param file pdf
     * @return pdf纸张格式
     * @throws IOException 异常
     */
    public static PageSizeEnum getPdfFormat(File file) throws IOException {
        Optional.ofNullable(file).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("文件不能为空"));
        PdfReader reader = new PdfReader(ByteArray.fromFile(file).value());
        int totalPages = reader.getNumberOfPages();
        PageSizeEnum pageSizeEnum = null;
        for (int i = 1; i <= totalPages; i++) {
            Rectangle pageSize = reader.getPageSize(i);
            float width = pageSize.getWidth();
            float height = pageSize.getHeight();
            if (pageSizeEnum != null) {
                if (!pageSizeEnum.equals(PageSizeEnum.convertToEnum(width, height))) {
                    throw ExceptionResultEnum.ERROR.exception("上传的试卷pdf中存在纸张格式不一样的");
                }
            } else {
                pageSizeEnum = PageSizeEnum.convertToEnum(width, height);
            }
//            PdfDictionary pdfDictionary = reader.getPageN(i);
//            PdfObject rotate = pdfDictionary.get(PdfName.ROTATE);
////            log.info("fileName:{},width:{},height:{},pageSizeEnum:{},rotateInt:{}", file.getName(), width, height, pageSizeEnum, rotate);
//            if (Objects.nonNull(rotate)) {
//                int rotateInt = Integer.parseInt(rotate.toString());
//                if (pageSizeEnum == PageSizeEnum.A3 && (rotateInt != 0 && rotateInt != 90)) {
//                    throw ExceptionResultEnum.ERROR.exception("上传的A3样式pdf请调整方向");
//                } else if (pageSizeEnum == PageSizeEnum.A4 && rotateInt > 0) {
//                    throw ExceptionResultEnum.ERROR.exception("上传的A4样式pdf请调整方向");
//                }
//            }
        }
        Long schoolId = SystemConstant.getHeadOrUserSchoolId();
        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
        SysConfig sysConfig = commonCacheService.addSysConfigCache(schoolId, SystemConstant.PDF_SIZE_LIST);
        sysConfig = Objects.isNull(sysConfig) ? commonCacheService.addSysConfigCache(SystemConstant.SYS_PDF_SIZE_LIST) : sysConfig;
        Optional.ofNullable(sysConfig).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未配置全局上传试卷规格"));

        String pdfSize = sysConfig.getConfigValue().replace("8K", "K8");
        List<String> pdfSizeList = Objects.nonNull(sysConfig) ? Arrays.asList(pdfSize.replaceAll("\\[", "").replaceAll("\\]", "").split(", ")) : null;

        PageSizeEnum finalPageSizeEnum = pageSizeEnum;
        long count = pdfSizeList.stream().filter(s -> finalPageSizeEnum.name().equalsIgnoreCase(s)).count();
        if (count == 0) {
            throw ExceptionResultEnum.ERROR.exception("pdf文件格式只能为" + sysConfig.getConfigValue());
        }
        return pageSizeEnum;
    }

//    /**
//     * 两页打印到一页（A4 -> A3）
//     *
//     * @param streamOfPDFFile 原卷
//     * @param outputStream    输出的试卷
//     * @param paginate        是否生成A3 每页页码
//     */
//    public static void concatPDFs(InputStream streamOfPDFFile, OutputStream outputStream, boolean paginate) {
//
//        Document document = new Document();
//        try {
//
//            //读取PDF
//            PdfReader pdfReader = new PdfReader(streamOfPDFFile);
//            int totalPages = pdfReader.getNumberOfPages();
//
//            //创建PDF Writer
//            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
//            document.open();
//            BaseFont baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
//            PdfContentByte contentByte = writer.getDirectContent();
//
//            Rectangle rec = pdfReader.getPageSize(1);
//            //新pdf为两个宽度
//            Rectangle newRec = new Rectangle(0, 0, rec.getWidth() * 2, rec.getHeight());
//            document.setPageSize(newRec);
//
//            PdfImportedPage page;
//            PdfImportedPage page2;
//            int currentPageNumber = 0;
//
//            //舍弃奇数的最后一页, 删除该设置后面不受影响
////            totalPages = totalPages >> 1 << 1;
//            for (int pageIndex = 0; pageIndex < totalPages; pageIndex += 2) {
//                document.newPage();
//                currentPageNumber++;
//
//                //原始第一页设置到左边
//                page = writer.getImportedPage(pdfReader, pageIndex + 1);
//                contentByte.addTemplate(page, 0, 0);
//
//                //第二页设置到右边
//                if (pageIndex + 2 <= totalPages) {
//                    page2 = writer.getImportedPage(pdfReader, pageIndex + 2);
//                    contentByte.addTemplate(page2, rec.getWidth(), 0);
//                }
//
//                //设置页码
//                if (paginate) {
//                    contentByte.beginText();
//                    contentByte.setFontAndSize(baseFont, 13);
//                    contentByte.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + SystemConstant.ORG_SPLIT + (totalPages / 2 + (totalPages % 2 == 0 ? 0 : 1)), newRec.getWidth() / 2, 17, 0);
//                    contentByte.endText();
//                }
//            }
//
//            outputStream.flush();
//            document.close();
//            outputStream.close();
//        } catch (Exception e) {
//            log.error(SystemConstant.LOG_ERROR, e);
//        } finally {
//            if (document.isOpen()) {
//                document.close();
//            }
//            try {
//                if (outputStream != null) {
//                    outputStream.close();
//                }
//            } catch (IOException ioe) {
//                log.error(SystemConstant.LOG_ERROR, ioe);
//            }
//        }
//    }

    /**
     * pdf添加水印
     *
     * @param inputFile     需要添加水印的文件
     * @param waterMarkName 需要添加的水印文字
     * @param opacity       水印字体透明度（0-1）
     * @param fontsize      水印字体大小
     * @param rotation      水印倾斜角度（0-360）
     */
    public static File addWaterMark(File inputFile, String[] waterMarkName, float opacity, int fontsize, int rotation) {
        if (!inputFile.exists()) {
            throw ExceptionResultEnum.ERROR.exception("试卷文件不存在");
        }

        if (waterMarkName.length == 0) {
            return inputFile;
        }

        DictionaryConfig dictionaryConfig = SpringContextHolder.getBean(DictionaryConfig.class);
        StringJoiner stringJoiner = new StringJoiner("");
        stringJoiner = SystemConstant.getDirName(stringJoiner, UploadFileEnum.PAPER, true);
        stringJoiner.add(SystemConstant.getNanoId()).add(SystemConstant.PDF_PREFIX);

        File zipFile = SystemConstant.getFileTempDirVarForZip(stringJoiner.toString(), null);
        String outputPath = stringJoiner.toString();
        PdfReader reader = null;
        PdfStamper stamper = null;
        File outputFile = null;
        try {
            outputFile = new File(outputPath);
            if (!outputFile.exists()) {
                outputFile.getParentFile().mkdirs();
                outputFile.createNewFile();
            }
            reader = new PdfReader(new FileInputStream(inputFile));
            stamper = new PdfStamper(reader, new FileOutputStream(outputPath));
            BaseFont base = BaseFont.createFont(AsianFontMapper.ChineseSimplifiedFont, AsianFontMapper.ChineseSimplifiedEncoding_H, BaseFont.NOT_EMBEDDED);
            PdfGState gs = new PdfGState();
            //这里是透明度设置
            gs.setFillOpacity(opacity);
            //这里是条纹不透明度
            gs.setStrokeOpacity(0.2f);
            int total = reader.getNumberOfPages() + 1;
            int textH = 0;
            int textW = 0;
            for (String s : waterMarkName) {
                JLabel label = new JLabel();
                FontMetrics metrics;

                label.setText(s);
                metrics = label.getFontMetrics(label.getFont());
                //字符串的高,   只和字体有关
                textH = metrics.getHeight();
                //字符串的宽
                textW = metrics.stringWidth(label.getText());
            }

            Rectangle pageRect;
            PdfContentByte under;
            //循环PDF，每页添加水印
            for (int i = 1; i < total; i++) {
                // 只打奇数页水印
                if (i % 2 == 0) {
                    continue;
                }
                pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);  //在内容上方添加水印
                under.saveState();
                under.setGState(gs);
                under.beginText();
                under.setFontAndSize(base, fontsize); //这里是水印字体大小
                for (int j = 0; j < waterMarkName.length; j++) {
                    under.showTextAligned(Element.ALIGN_LEFT, waterMarkName[j], 20, pageRect.getHeight() - 20 - (j * textH), rotation);
                }
                //添加水印文字
                under.endText();
            }
            return outputFile;
        } catch (IOException | DocumentException e) {
            System.out.println("添加水印失败！错误信息为: " + e);
            e.printStackTrace();
        } finally {
            //关闭流
            if (stamper != null) {
                try {
                    stamper.close();
                } catch (DocumentException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                reader.close();
            }
            if (outputFile.exists()) {
//                outputFile.delete();
            }
            if (Objects.nonNull(zipFile)) {
                zipFile.delete();
            }
        }
        return null;
    }

    /**
     * html转pdf文件
     *
     * @param htmlContent html内容
     */
    public static File htmlToPdf(String htmlContent) {
        File htmlFileTemp = null;
        try {
            htmlFileTemp = SystemConstant.getFileTempVar(SystemConstant.HTML_PREFIX);
            FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), htmlFileTemp);

            File pdfFileTemp = SystemConstant.getFileTempVar(SystemConstant.PDF_PREFIX);
            // html转pdf
            HtmlToPdfUtil.convert(htmlFileTemp.getPath(), pdfFileTemp.getPath(), PageSizeEnum.A3);
            return pdfFileTemp;
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("html文件转pdf文件失败");
        } finally {
            if (htmlFileTemp != null) {
                FileUtil.deleteFile(htmlFileTemp);
            }
        }
    }

    public static String md5FileName(String fileName) {
        return DigestUtils.md5DigestAsHex(fileName.getBytes(StandardCharsets.UTF_8));
    }
}
