package com.bonus.common.core.utils.poi;
import com.bonus.common.core.utils.StringUtils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.Getter;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;

import javax.servlet.http.HttpServletResponse;
import java.io.*;

public class PdfUtil implements DocumentUtil {

    /**
     * -- GETTER --
     *  获取文档对象
     */
    private final Document document;
    private final PdfWriter writer;
    private BaseFont baseFont;
    private int defaultFontSize = 12;
    /**
     * 初始化 PDF 文档
     * @param pdfPath PDF 本地文件路径
     * @param fontPath 指定字体路径并将字体嵌入到pdf文档中保证在其他计算机上以同样字体显示，如果为空，则使用默认支持中文字体
     * @param defaultFontSize 指定字体大小，传入非整数值则默认为12
     * @throws DocumentException 文档异常处理
     * @throws IOException       IO 异常处理
     */
    public PdfUtil(String pdfPath, String fontPath, int defaultFontSize) throws DocumentException, IOException {
        createBaseFont(fontPath);
        if (defaultFontSize > 0) {
            this.defaultFontSize = defaultFontSize;
        }
        document = new Document();
        writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
        document.open();
    }


    /**
     * 获取文档对象，以便对文档做其他自定义的操作
     */
    public Document getDocument() {
        return document;
    }

    /**
     * 初始化 PDF 文档
     * @param response http响应
     * @param fontPath 指定字体路径，如果为空，则使用默认支持中文字体
     * @param defaultFontSize 指定字体大小，默认为12
     * @throws DocumentException 文档异常处理
     * @throws IOException       IO 异常处理
     */
    public PdfUtil (HttpServletResponse response, String fontPath, int defaultFontSize) throws DocumentException, IOException {
        createBaseFont(fontPath);
        if (defaultFontSize > 0) {
            this.defaultFontSize = defaultFontSize;
        }
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"generated.pdf\"");
        document = new Document();
        writer = PdfWriter.getInstance(document, response.getOutputStream());
        document.open();
    }


    public BaseFont getBaseFont() {
        return baseFont;
    }

    /*
    * 设置PDF文档的元数据中的标题（通常通过“文件” -> “属性”)查看。
    * @param title 标题内容
     */
    public void addTitle(String title){
        document.addTitle(title);
    }

    private void createBaseFont(String fontPath) throws DocumentException, IOException {
        if (StringUtils.isNotBlank(fontPath)) {
            File fontFile = new File(fontPath);
            if (!fontFile.exists()) {
                baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            } else {
                baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            }
        }
        else {
            baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        }

    }
    /**
     * 添加段落
     * @param text 段落文本
     * @param font 字体样式，为空则使用默认字体样式
     * @throws DocumentException 文档异常处理
     */
    public Paragraph addParagraph(String text, Font font) throws DocumentException {
        if (font == null) {
            font = new Font(baseFont, defaultFontSize, Font.NORMAL);
        }
        Paragraph paragraph = new Paragraph(text, font);
        document.add(paragraph);
        return paragraph;
    }

    /**
     * 添加表格
     * @param headers  表头数组
     * @param content  表格内容
     * @param numCols  表格列数
     * @param font 字体样式，为空则使用默认字体样式
     * @throws DocumentException 文档异常处理
     */
    public void addTable(String[] headers, String[][] content, int numCols, Font font) throws DocumentException {
        if (font == null) {
            font = new Font(baseFont, defaultFontSize, Font.NORMAL);
        }
        PdfPTable table = new PdfPTable(numCols);

        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, font));
            table.addCell(cell);
        }

        for (String[] row : content) {
            for (String cellData : row) {
                table.addCell(new Phrase(cellData, font));
            }
        }

        document.add(table);
    }

    /**
     * 添加图片
     * @param imagePath 图片文件路径
     * @throws IOException       IO 异常处理
     * @throws DocumentException 文档异常处理
     * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素
     * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素
     */
    public void addImage(String imagePath, int width, int height) throws IOException, DocumentException {
        Image image = Image.getInstance(imagePath);
        // 根据需求调整图片大小
        image.scaleToFit(width, height);
        document.add(image);
    }

    /**
     * 添加段落并设置样式
     *
     * @param text  段落文本
     * @param bold  是否加粗
     * @param italic 是否斜体
     * @param fontSize 字体大小
     * @throws DocumentException 文档异常处理
     */
    public void addStyledParagraph(String text, boolean bold, boolean italic, int fontSize, Font font) throws DocumentException {
        if (font == null) {
            font = new Font(baseFont, defaultFontSize, Font.NORMAL);
        }
        if (bold) {
            font.setStyle(Font.BOLD);
        }
        if (italic) {
            font.setStyle(Font.ITALIC);
        }
        addParagraph(text, font);
    }

    /**
     * 创建饼状图，并插入到文档中
     *
     * @param title 图表标题
     * @param categories 目录轴的标签
     * @param values  数据轴的标签
     * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素
     * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素
     */
    public void addPieChart( String title, String[] categories, double[] values, int width, int height) throws IOException, DocumentException {
        // 使用 JFreeChart 创建一个饼状图
        JFreeChart pieChart = createPieChart(title, categories, values);
        addChartToDocument(pieChart,width,height);
    }

    /**
     * 创建柱状图，并插入到文档中
     * @param title 图表标题
     * @param categoryAxisLabel 目录轴的标签
     * @param valueAxisLabel  数据轴的标签
     * @param  rowKeys 目录轴每行的key
     * @param  columnKeys 数据轴每列的key
     * @param data  数据
     * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素
     * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素
     */
    public void addBarChart(String title, String categoryAxisLabel, String valueAxisLabel,
                            String[] rowKeys, String[] columnKeys, double[][] data, int width, int height) throws IOException, DocumentException {

        JFreeChart barChart = createBarChart(title, categoryAxisLabel, valueAxisLabel, rowKeys, columnKeys, data);
        addChartToDocument(barChart,width,height);
    }

    /**
     * 将 JFreeChart 图表添加到 PDF 文档中
     *
     * @param chart JFreeChart 对象
     * @throws IOException       IO 异常处理
     * @throws DocumentException 文档异常处理
     * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素
     * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素
     */
    private void addChartToDocument(JFreeChart chart, int width, int height) throws IOException, DocumentException {
        width = (width > 0) ? width : 400;
        height = (height > 0) ? height : 400;
        if (chart == null) {
            return;
        }
        ByteArrayOutputStream chartOutput = new ByteArrayOutputStream();
        ChartUtils.writeChartAsPNG(chartOutput, chart, width, height);
        Image chartImage = Image.getInstance(chartOutput.toByteArray());
        chartImage.scaleToFit(width, height);
        document.add(chartImage);
    }

    /**
     * 关闭文档
     */
    public void close() {
        document.close();
    }
}
