package com.bcxin.auth.common.utils;

import com.bcxin.auth.common.vo.CommonClass;
import org.apache.commons.beanutils.BeanUtils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class PDFUtils {
    //日志
    final static Logger logger = LoggerFactory.getLogger(PDFUtils.class);
    /***
     * 生成PDF文件
     * @param templatePath 模块路径
     * @param pdfPath 生成pdf文件路径
     * @param obj 表单赋值对象
     */
    public static void createPDFForTemplate(String templatePath,String pdfPath,Object obj) throws IOException, DocumentException {
        PdfReader reader = null;
        FileOutputStream out = null;
        ByteArrayOutputStream bos= null;
        PdfStamper stamper = null;
        Document doc = null;
        try {
            //输出流
            out = new FileOutputStream(pdfPath);
            //读取pdf模板
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            //pdf表单相关信息展示
            AcroFields form = stamper.getAcroFields();
            Iterator<String> it = form.getFields().keySet().iterator();
            while (it.hasNext()) {
                //name就是pdf模版中各个文本域的名字
                String fieldName = it.next();
                System.out.println(fieldName);
                //设置表单字段的值
                String propertyValue = BeanUtils.getProperty(obj, fieldName);

                System.out.println("name:"+fieldName+"  value:"+propertyValue);
                form.setField(fieldName, propertyValue);
            }
            // 如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.setFormFlattening(true);
            stamper.close();
            //生成新的pdf文件
            doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        } catch (DocumentException e) {
            logger.error(e.getMessage(),e);
        } catch (IllegalAccessException e) {
            logger.error(e.getMessage(),e);
        } catch (InvocationTargetException e) {
            logger.error(e.getMessage(),e);
        } catch (NoSuchMethodException e) {
            logger.error(e.getMessage(),e);
        } finally {
            //最后关闭相关的流
            if(stamper!=null){
                stamper.close();
            }
            if(doc!=null){
                doc.close();
            }
        }
    }

    public static void createPDF(String templatePath, String pdfPath, Object obj) throws IOException, DocumentException {
        PdfReader reader = null;
        FileOutputStream out = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper = null;
        Document doc = null;

        try {
            // 输出流
            out = new FileOutputStream(pdfPath);

            // 读取 PDF 模板
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);

            // 加载字体（从 JAR 中）
            BaseFont baseFont = loadFontFromJar("fonts/宋体.ttf");

            // 获取表单字段
            AcroFields form = stamper.getAcroFields();
            form.addSubstitutionFont(baseFont);
            Iterator<String> it = form.getFields().keySet().iterator();
            while (it.hasNext()) {
                String fieldName = it.next();
                String propertyValue = BeanUtils.getProperty(obj, fieldName);
                System.out.println("name: " + fieldName + " value: " + propertyValue);
                form.setField(fieldName, propertyValue);
                form.setFieldProperty(fieldName, "textfont", BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.EMBEDDED), null);
            }

            // 如果为 false 那么生成的 PDF 文件还能编辑，一定要设为 true
            stamper.setFormFlattening(true);
            stamper.close();

            // 生成新的 PDF 文件
            doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            if (stamper != null) {
                stamper.close();
            }
            if (doc != null) {
                doc.close();
            }
        }
    }

    // 从 JAR 内加载字体
    private static BaseFont loadFontFromJar(String fontPath) throws IOException, DocumentException {
        InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontPath);
        if (fontStream == null) {
            throw new FileNotFoundException("Font file not found: " + fontPath);
        }

        File tempFile = File.createTempFile("font", ".ttf");
        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fontStream.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
        }

        BaseFont baseFont = BaseFont.createFont(tempFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        tempFile.deleteOnExit();
        return baseFont;
    }

    public static void addPDFChange(String templatePDF, String outFile, List<CommonClass> pdfChangeDTOList) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(templatePDF);
        PdfStamper ps = new PdfStamper(reader, new FileOutputStream(outFile)); // 生成的输出流
        AcroFields s = ps.getAcroFields();

        insertText(ps,s,pdfChangeDTOList);
        ps.close();
        reader.close();
    }

    public static void main(String[] args) throws Exception {
        List<String> pdfFiles = new ArrayList<>();
        pdfFiles.add("D:\\data\\logs\\C610100queueId_601.pdf");
        pdfFiles.add("D:\\data\\logs\\C610700queueId_620.pdf");
        Document document = new Document(PageSize.A4); // 横向A4纸
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("D:\\data\\logs\\merged.pdf"));
        document.open();
        PdfContentByte canvas = writer.getDirectContent();

// 读取两个PDF文件
        PdfReader reader1 = new PdfReader("D:\\data\\logs\\C610100queueId_601.pdf");
        PdfReader reader2 = new PdfReader("D:\\data\\logs\\C610700queueId_620.pdf");

// 获取两个PDF的第一页内容
        PdfImportedPage page1 = writer.getImportedPage(reader1, 1);
        PdfImportedPage page2 = writer.getImportedPage(reader2, 1);
        float scaleX = PageSize.A4.getWidth() / page1.getWidth();
        float scaleY = PageSize.A4.getHeight() / (page1.getHeight()*2);
        float scale2X = PageSize.A4.getWidth() / page2.getWidth();
        float scale2Y = PageSize.A4.getHeight() / (page2.getHeight()*2);
        canvas.addTemplate(page1, scaleX, 0, 0, scaleY, -25, PageSize.A4.getHeight()/2);
        canvas.addTemplate(page2, scale2X, 0, 0, scale2Y, -25, 41);

        document.close();
    }

    /**
     * <b> 2张pdf合并成一张pdf，至少需要一张pdf </b>
     * 注：陕西保安员电子证书打印专用
     * @param inpdf1 电子证书绝对路径1
     * @param inpdf2 电子证书绝对路径2
     * @param outpdf 输出pdf绝对路径
     * @author ZXF
     * @create 2025/02/28 0028 16:01
     * @version
     * @注意事项 </b>
     */
    public static void mergePdf(String inpdf1, String inpdf2, String outpdf) throws Exception {
        if (StringUtils.isEmpty(inpdf1)) {
            throw new FileNotFoundException("Font file not found: " + inpdf1);
        }
        // 步骤1：扁平化签名注释（将签名渲染为页面内容）
        byte[] flattenedPdf1 = flattenSignatureAnnotations(inpdf1);
        byte[] flattenedPdf2 = null;
        if (StringUtils.isNotEmpty(inpdf2)) {
            flattenedPdf2 = flattenSignatureAnnotations(inpdf2);
        }

        Document document = new Document(PageSize.A4); // 横向A4纸
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outpdf));
        document.open();
        PdfContentByte canvas = writer.getDirectContent();

        PdfReader reader1 = new PdfReader(flattenedPdf1);
        PdfImportedPage page1 = writer.getImportedPage(reader1, 1);
        float scaleX = PageSize.A4.getWidth() / page1.getWidth();
        float scaleY = PageSize.A4.getHeight() / (page1.getHeight()*2);
        canvas.addTemplate(page1, scaleX, 0, 0, scaleY, -25, PageSize.A4.getHeight()/2);
        if (StringUtils.isNotEmpty(inpdf2)) {
            PdfReader reader2 = new PdfReader(flattenedPdf2);
            PdfImportedPage page2 = writer.getImportedPage(reader2, 1);
            float scale2X = PageSize.A4.getWidth() / page2.getWidth();
            float scale2Y = PageSize.A4.getHeight() / (page2.getHeight() * 2);
            canvas.addTemplate(page2, scale2X, 0, 0, scale2Y, -25, 41);
        }
        document.close();
    }

    public static void mergePdf1(String inpdf1, String inpdf2, String outpdf,float bl1,float bl2) throws Exception {
        if (StringUtils.isEmpty(inpdf1)) {
            throw new FileNotFoundException("Font file not found: " + inpdf1);
        }
        // 步骤1：扁平化签名注释（将签名渲染为页面内容）
        byte[] flattenedPdf1 = flattenSignatureAnnotations(inpdf1);
        byte[] flattenedPdf2 = null;
        if (StringUtils.isNotEmpty(inpdf2)) {
            flattenedPdf2 = flattenSignatureAnnotations(inpdf2);
        }

        Document document = new Document(PageSize.A4); // 横向A4纸
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outpdf));
        document.open();
        PdfContentByte canvas = writer.getDirectContent();

        PdfReader reader1 = new PdfReader(flattenedPdf1);
        Rectangle origSize = reader1.getPageSize(1);
        float origWidth = origSize.getWidth()*bl1;
        float origHeight = origSize.getHeight()*bl1;

        // 计算可用区域（A4纸的上半部或下半部）
        float availableWidth = PageSize.A4.getWidth(); // 左右各留20mm边距
        float availableHeight = PageSize.A4.getHeight() / 2; // 上下各留20mm边距
        // 计算保持宽高比的缩放比例（关键修改）
        float widthRatio = availableWidth / origWidth;
        float heightRatio = availableHeight / origHeight;
        float scale = Math.min(widthRatio, heightRatio); // 取最小比例保持宽高比
        // 计算缩放后的实际尺寸
        float scaledWidth = origWidth * scale;
        // 计算居中位置
        float x = (PageSize.A4.getWidth() - scaledWidth) / 2;

        // 添加缩放后的页面（去除多余的X轴偏移）
        PdfImportedPage page = writer.getImportedPage(reader1, 1);
        float scaleY = PageSize.A4.getHeight() / (page.getHeight()*2);
        canvas.addTemplate(page, scale, 0, 0, scale, x-6.5, (PageSize.A4.getHeight()/2)+10);
        // 单独放大签名图像
//        scaleAndPlaceSignatures(canvas, writer, reader1, scale, (float)(x-6.5), (PageSize.A4.getHeight()/2)+10);
        if (StringUtils.isNotEmpty(inpdf2)) {
            PdfReader reader2 = new PdfReader(flattenedPdf2);

            Rectangle origSize2 = reader2.getPageSize(1);
            System.out.println(origSize.getWidth());
            float origWidth2 = origSize2.getWidth()*bl2;
            float origHeight2 = origSize2.getHeight()*bl2;

            // 计算可用区域（A4纸的上半部或下半部）
            float availableWidth2 = PageSize.A4.getWidth(); // 左右各留20mm边距
            float availableHeight2 = PageSize.A4.getHeight() / 2; // 上下各留20mm边距

            // 计算保持宽高比的缩放比例（关键修改）
            float widthRatio2 = availableWidth2 / origWidth2;
            float heightRatio2 = availableHeight2 / origHeight2;
            float scale2 = Math.min(widthRatio2, heightRatio2); // 取最小比例保持宽高比
            // 添加缩放后的页面（去除多余的X轴偏移）
            PdfImportedPage page2 = writer.getImportedPage(reader2, 1);
            float scale2Y = PageSize.A4.getHeight() / (page2.getHeight() * 2);
            canvas.addTemplate(page2, scale2, 0, 0, scale2Y, x-6.5, 51);
        }
        document.close();
    }

    /**
     * 扁平化PDF中的签名注释（将注释渲染为页面内容）
     */
    private static byte[] flattenSignatureAnnotations(String inputPath) throws Exception {

        try(ByteArrayOutputStream baos = new ByteArrayOutputStream();) {
            PdfReader reader = new PdfReader(inputPath);
            PdfStamper stamper = new PdfStamper(reader, baos);
            stamper.setFormFlattening(true);  // 使签名成为页面的一部分
            stamper.close();
            reader.close();
            return baos.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }
        // 关键步骤：启用表单扁平化，将签名注释转为页面内容


        return null;
    }

    // 放大倍数
    private static final float SIGNATURE_SCALE = 0.95f;

    /**
     * 只放大签名图像
     */
    private static void scaleAndPlaceSignatures(
            PdfContentByte canvas,
            PdfWriter writer,
            PdfReader reader,
            float pageScale,
            float pageX,
            float pageY
    ) throws Exception {
        // 获取页面中的所有注释（签名）
        PdfDictionary pageDict = reader.getPageN(1);
        PdfArray annots = pageDict.getAsArray(PdfName.ANNOTS);

        if (annots == null) return;

        for (int i = 0; i < annots.size(); i++) {
            PdfDictionary annot = annots.getAsDict(i);
            PdfName subtype = annot.getAsName(PdfName.SUBTYPE);

            // 检查是否为签名注释
            if (PdfName.WIDGET.equals(subtype) || PdfName.SIG.equals(subtype)) {
                PdfArray rectArray = annot.getAsArray(PdfName.RECT);
                if (rectArray == null || rectArray.size() < 4) continue;

                // 获取签名位置和尺寸
                float llx = rectArray.getAsNumber(0).floatValue();
                float lly = rectArray.getAsNumber(1).floatValue();
                float urx = rectArray.getAsNumber(2).floatValue();
                float ury = rectArray.getAsNumber(3).floatValue();

                float width = urx - llx;
                float height = ury - lly;

                // 计算放大后的签名尺寸
                float scaledWidth = width * SIGNATURE_SCALE;
                float scaledHeight = height * SIGNATURE_SCALE;

                // 计算放大后的位置（居中）
                float centerX = llx + width / 2;
                float centerY = lly + height / 2;
                float newX = centerX - scaledWidth / 2;
                float newY = centerY - scaledHeight / 2;

                // 获取签名内容流（包含签名图像）
                PdfStream xobject = annot.getAsStream(PdfName.AP);
                if (xobject != null) {
                    PdfIndirectReference ref = xobject.getIndRef();
                    if (ref != null) {
                        // 导入签名图像
                        PdfImportedPage signaturePage = writer.getImportedPage(reader, 1);

                        // 计算在合并页面中的位置
                        float canvasX = pageX + newX * pageScale;
                        float canvasY = pageY + newY * pageScale;

                        // 添加放大后的签名图像
                        canvas.addTemplate(
                                signaturePage,
                                pageScale * SIGNATURE_SCALE,
                                0,
                                0,
                                pageScale * SIGNATURE_SCALE,
                                canvasX,
                                canvasY
                        );
                    }
                }
            }
        }
    }

    /**
     * 将PDF页面缩放到指定高度并添加到画布
     */
    private static void addScaledPage(
            PdfContentByte canvas,
            PdfWriter writer,
            byte[] pdfData,
            float yOffset,
            boolean isTop
    ) throws Exception {
        PdfReader reader = new PdfReader(pdfData);
        PdfImportedPage page = writer.getImportedPage(reader, 1);

        // 获取原始页面尺寸
        Rectangle pageSize = reader.getPageSize(1);
        float origWidth = pageSize.getWidth();
        float origHeight = pageSize.getHeight();

        // 计算缩放比例（保持宽高比）
        float availableHeight = PageSize.A4.getHeight() / 2;
        float scale = Math.min(
                (PageSize.A4.getWidth() - 50) / origWidth,  // 留出边距
                availableHeight / origHeight
        );

        // 计算位置（水平居中）
        float x = (PageSize.A4.getWidth() - (origWidth * scale)) / 2;
        float y = isTop
                ? PageSize.A4.getHeight() - availableHeight + (availableHeight - origHeight * scale) / 2
                : yOffset + (availableHeight - origHeight * scale) / 2;

        // 添加缩放后的页面
        canvas.addTemplate(page, scale, 0, 0, scale, x, y);
        reader.close();
    }


    /**
     * 插入文本
     */
    public static void insertText(PdfStamper ps, AcroFields s, List<CommonClass> pdfChangeDTOList)  throws IOException, DocumentException
    {
        //获取字段
        List<AcroFields.FieldPosition> list = s.getFieldPositions("change");
        Rectangle rect = list.get(0).position;
        PdfContentByte cb = ps.getOverContent(1);
        //生成四列表格
        PdfPTable table = new PdfPTable(4);
        //设置表格具体宽度
        table.setTotalWidth(270);
        //设置每一列所占的长度
        table.setWidths(new float[]{14f, 29f,16f, 20f});
        //解决中文在pdf不显示的问题
        BaseFont bfChinese = BaseFont.createFont( "STSongStd-Light" ,"UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
        Font font_10 = new Font(bfChinese, 10,Font.NORMAL);
        Font font_7 = new Font(bfChinese, 8,Font.NORMAL);
        Font font_12 = new Font(bfChinese, 12,Font.NORMAL);
        table.addCell(changeCellAlignment("项   目", font_12,true,true,28F));
        table.addCell(changeCellAlignment("变更后内容", font_12,true,true,28F));
        table.addCell(changeCellAlignment("变更时间", font_12,true,true,28F));
        table.addCell(changeCellAlignment("变更专用章", font_12,true,true,28F));
        //判断是否有变更内容 edit
        if(pdfChangeDTOList!=null) {
            for (CommonClass pdfChangeDTO : pdfChangeDTOList) {
                table.addCell(changeCellAlignment(pdfChangeDTO.getField1(), font_10, true, true,0.0F));
                table.addCell(changeCellAlignment(pdfChangeDTO.getField2(), font_7, false, true,0.0F));
                table.addCell(changeCellAlignment(pdfChangeDTO.getField3(), font_10, true, true,0.0F));
                PdfPCell blankCell = new PdfPCell();
                blankCell.setMinimumHeight(28);
                table.addCell(blankCell);
            }
        }else{
            //如果为空设置一个空数组
            pdfChangeDTOList  =  new ArrayList<CommonClass>();
        }
        //内容
        int size=7-pdfChangeDTOList.size();
        for (int i=0;i<size;i++){
            PdfPCell blankCell = new PdfPCell();
            blankCell .setMinimumHeight(28);
            table.addCell(blankCell);
            table.addCell(new Paragraph("",font_10));
            table.addCell(new Paragraph("",font_10));
            table.addCell(new PdfPCell(new Phrase("")));
        }
        //写入
        table.writeSelectedRows(0, -1, rect.getLeft(), rect.getTop(), cb);
    }

    private static PdfPCell changeCellAlignment(String projectName, Font font,boolean horizontal,boolean vertical,float minimumHeight) {
        //表单
        Paragraph paragraph= new Paragraph(projectName,font);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        PdfPCell cell1 = new PdfPCell();
        cell1.setUseAscender(true);
        if (horizontal) {
            cell1.setHorizontalAlignment(Element.ALIGN_CENTER); //水平居中
        }
        if (vertical) {
            cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);//垂直居中
        }
        cell1.setPhrase(paragraph);
        cell1.setMinimumHeight(minimumHeight);
        return cell1;
    }


}
