package com.hw.printer.utils;

import com.hw.common.core.exception.ServiceException;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import org.apache.pdfbox.pdmodel.PDDocument;

import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;

import javax.annotation.PostConstruct;
import javax.print.*;

import java.awt.print.*;
import java.io.*;
import java.util.HashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


/**
 * @author wanghao
 * @date 2022/4/24  14:52
 */
@Component
public class HwPrintUtil {

    private static final Logger log = LoggerFactory.getLogger(HwPrintUtil.class);

    /**
     * 打印机映射路径
     */
    public static String localPrintPath;

    /**
     * PDF模板路径
     */
    public static String pdfTemplatePath;

    /**
     * 生成PDF文件路径
     */
    public static String generatePath;

    /**
     * 打印机List
     */
    private static PrintService[] printServices;

    /**
     * 打印机服务
     */
    private static PrintService printService = null;

    /**
     * 项目启动时，初始化打印机参数
     */
    @PostConstruct
    public static void findPrinters() {
        printServices = PrintServiceLookup.lookupPrintServices(null, null);
        System.out.println("Bean已初始化，执行@PostConstruct注解的方法");
    }

    /**
     * 打印方法
     *
     * @param params
     * @return
     */
    public static String printBarCode(HashMap<String, String> params) {
        //解析参数生成打印图片
        localPrintPath = params.get("localPrintPath");
        pdfTemplatePath = params.get("pdfTemplatePath");
        generatePath = params.get("generatePath");
        String barcodeInfo = params.get("barcodeInfo");
        String batchCode = params.get("batchCode");
        String materialName = params.get("materialName");
        String date = params.get("date");
        initPrintService();
        File outputFile = printQRCode(barcodeInfo, batchCode, materialName, date);
        try {
            printPdf(outputFile);
            log.info("打印条码printBarCode方法,条码内容：" + barcodeInfo);
            return localPrintPath;
        } catch (Exception e) {
            log.error("打印条码printPdf异常：" + e);
            throw new ServiceException("打印条码printPdf异常：" + e);
        }
    }

    /**
     * 打印二维码到PDF文件
     *
     * @param barcodeInfo 条形码信息
     * @param batchCode   批次代码
     * @param materialName 物料名称
     * @param date        日期
     * @return 生成的PDF文件
     */
    public static File printQRCode(String barcodeInfo, String batchCode, String materialName, String date) {
        try {
            // 生成PDF文件
            File generateFile = new File(generatePath);
            FileOutputStream out = new FileOutputStream(generateFile);
            // 打印模板PDF
            PdfReader reader = new PdfReader(pdfTemplatePath);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            // 修改PDF文档的PdfStamper实例，将修改后的内容输出到内存中的字节数组
            PdfStamper stamper = new PdfStamper(reader, bos);
            // 动态地将变量的值填充到PDF表单相应字段
            AcroFields form = stamper.getAcroFields();
            form.setField("code", barcodeInfo);
            form.setField("name", materialName);
            form.setField("spe", batchCode);
            form.setField("data", date);
            //获取位置(左上右下)
            AcroFields.FieldPosition fieldPosition = form.getFieldPositions("qrcode").get(0);
            // 绘制二维码
            float width = fieldPosition.position.getRight() - fieldPosition.position.getLeft();
            BarcodeQRCode pdf417 = new BarcodeQRCode(barcodeInfo, (int) width, (int) width, null);
            // 生成二维码图像
            Image image128 = pdf417.getImage();
            // 条码位置
            image128.setAbsolutePosition(fieldPosition.position.getLeft(), fieldPosition.position.getBottom());
            // 获取PDF的第一页
            PdfContentByte cb = stamper.getOverContent(1);
            cb.addImage(image128);
            // 设置表单不可编辑（即将表单字段内容固定到PDF中）
            stamper.setFormFlattening(true);
            // 关闭PdfStamper
            stamper.close();
            // 创建一个新的文档对象
            Document doc = new Document();
            // 创建 PdfCopy 对象，关联到输出流
            PdfCopy copy = new PdfCopy(doc, out);
            // 打开文档
            doc.open();
            // 从内存中的字节数组创建一个 PdfImportedPage 对象
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            // 将导入的页面添加到新文档中
            copy.addPage(importPage);
            // 关闭文档
            doc.close();
            return generateFile;
        } catch (Exception e) {
            log.error("打印条码生成PDF异常：" + e);
        }
        return null;
    }

    /**
     * 打印条形码到PDF文件
     *
     * @param barcodeInfo 条形码信息
     * @param batchCode   批次代码
     * @param materialName 物料名称
     * @param date        日期
     * @return 生成的PDF文件
     */
    public static File printBarCode(String barcodeInfo, String batchCode, String materialName, String date) {
        try {
            // 生成PDF文件
            File generateFile = new File(generatePath);
            FileOutputStream out = new FileOutputStream(generateFile);
            // 加载PDF模板
            PdfReader reader = new PdfReader(pdfTemplatePath);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            // 创建PdfStamper以修改PDF并将输出到字节数组
            PdfStamper stamper = new PdfStamper(reader, bos);
            // 动态填充表单字段
            AcroFields form = stamper.getAcroFields();
            form.setField("code", barcodeInfo);
            form.setField("name", materialName);
            form.setField("spe", batchCode);
            form.setField("data", date);
            // 获取条形码字段的位置
            AcroFields.FieldPosition fieldPosition = form.getFieldPositions("qrcode").get(0);
            // 绘制条形码
            float width = fieldPosition.position.getRight() - fieldPosition.position.getLeft();
            Barcode39 barcode39 = new Barcode39();
            barcode39.setCode(barcodeInfo);
            barcode39.setBarHeight(50f); // 根据需要调整条形码大小
            Image barcodeImage = barcode39.createImageWithBarcode(stamper.getOverContent(1), null, null);
            barcodeImage.setAbsolutePosition(fieldPosition.position.getLeft(), fieldPosition.position.getBottom());
            // 将条形码图像添加到第一页
            stamper.getOverContent(1).addImage(barcodeImage);
            // 将表单平铺（使其不可编辑）
            stamper.setFormFlattening(true);
            // 关闭PdfStamper
            stamper.close();
            // 创建新文档
            Document doc = new Document();
            // 创建关联到输出流的PdfCopy对象
            PdfCopy copy = new PdfCopy(doc, out);
            // 打开文档
            doc.open();
            // 从字节数组创建一个PdfImportedPage对象
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            // 将导入的页面添加到新文档中
            copy.addPage(importPage);
            // 关闭文档
            doc.close();
            return generateFile;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 打印PDF
     *
     * @param pdfFile 要打印的PDF文件
     * @throws IOException 如果PDF加载或打印失败
     */
    private static void printPdf(File pdfFile) throws IOException {
        PDDocument document = null;
        try {
            document = PDDocument.load(pdfFile);
            //打印的页面的大小和方向
            PageFormat pageFormat = new PageFormat();
            //设置打印方向 PORTRAIT 竖向  REVERSE_LANDSCAPE 横向
            pageFormat.setOrientation(PageFormat.PORTRAIT);
            Paper paper = new Paper();
            // 纸的大小
            paper.setSize(221, 200);
            // Print 区域
            paper.setImageableArea(2, -15, 221, 200);
            pageFormat.setPaper(paper);
            Book book = new Book();
            PDFPrintable printable = new PDFPrintable(document, Scaling.SCALE_TO_FIT);
            book.append(printable, pageFormat, document.getNumberOfPages());
            PrinterJob job = PrinterJob.getPrinterJob();
            job.setPrintService(printService);
            job.setPageable(book);
            job.defaultPage();
            try {
                job.print();
            } catch (PrinterException e) {
                throw new IOException("PDF打印失败:", e);
            }
        } catch (PrinterException e) {
            throw new ServiceException("打印机服务错误:" + e);
        } finally {
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    // 处理关闭文档时可能出现的异常
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 导出为金山PDF
     * 导出为WPS PDF
     * 发送至 OneNote 2013
     * Microsoft XPS Document Writer
     * Microsoft Print to PDF
     * Fax
     * \\10.11.43.159\HP LaserJet MFP M129-M134
     * \\10.11.43.159\HP Laser NS 1020
     */
    public static void initPrintService() {
        for (PrintService service : printServices) {
            System.out.println(service.getName());
            if (service.getName().contains(localPrintPath)) {
                printService = service;
                break;
            }
        }
        if (printService == null) {
            throw new ServiceException("打印机配置错误!");
        }
    }
}
