package com.xinyilu.common.utils.document;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.xinyilu.common.utils.jreechart.FreeChartDocumentUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @Description PDF文档生成工具类
 * @Author 纪寒
 * @Date 2022-09-23 10:28:12
 * @Version 1.0
 */
public class CreateDocumentUtils {

    /**
     * 创建PDF文档方法
     *
     * @param outputStream      流
     * @param tableContentList  产品净值
     * @param tableContentList2 收益率指标
     * @param linePort          净值走势
     * @param tableContentList3 风险指标
     * @param piePort           组合配置
     * @param tableContentList4 产品信息
     * @throws Exception 异常信息
     */
    public static void createTable(ByteArrayOutputStream outputStream, List<VehicleIndex1> tableContentList,
                                   List<VehicleIndex2> tableContentList2, Map<String, Map<String, BigDecimal>> linePort,
                                   List<VehicleIndex3> tableContentList3, Map<String, BigDecimal> piePort,
                                   List<VehicleIndex3> tableContentList4) throws Exception {
        // 创建一个文档（默认大小A4，边距36, 36, 36, 36）
        Document document = new Document();
        // 设置文档大小
        document.setPageSize(PageSize.A4);
        // 设置边距，单位都是像素，换算大约1厘米=28.33像素
        document.setMargins(50, 50, 50, 50);
        // 创建writer，通过writer将文档写入磁盘
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);
        //标题
        String title = "XXXX投资基金周度报告";
        //设置标题时间
        String createHeadTime = "报告截止日期：2022-07-08";
        // 打开文档，只有打开后才能往里面加东西
        document.open();
        // 设置作者
        document.addAuthor("纪寒");
        // 设置创建者
        document.addCreator("小明");
        // 设置主题
        document.addSubject(title);
        // 设置标题
        document.addTitle(title);
        // 设置标题
        Paragraph paragraphHead1 = createHead1(title);
        document.add(paragraphHead1);
        // 设置标题时间
        Paragraph paragraphHeadTime = createHeadTime(createHeadTime);
        document.add(paragraphHeadTime);
        //产品净值表格
        buildProductNetValue(document, tableContentList);
        //收益率指标
        buildYield(document, tableContentList2);
        //净值走势折线图
        FreeChartDocumentUtil.createLinePortImage(document, "净值走势", linePort, "日期", "净值");
        //风险指标
        buildRiskIndicator(document, tableContentList3);
        //创建饼状图
        FreeChartDocumentUtil.createPiePortImage(document, "组合配置", piePort);
        //产品信息
        buildProductDetail(document, tableContentList4);
        // 关闭文档，才能输出
        document.close();
        writer.close();
    }

    /**
     * 根据传入的参数生成PDF文档使用的字体
     *
     * @param fontSize 字体大小
     * @param fontMode 字体正常、加粗、下划线等
     * @return 返回生成的字体
     */
    private static Font createFont(int fontSize, int fontMode) throws DocumentException, IOException {
        BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        return new Font(bfChinese, fontSize, fontMode, BaseColor.BLACK);
    }

    /**
     * 设置一级标题
     *
     * @param title 标题内容
     * @return 标题段落
     */
    private static Paragraph createHead1(String title) throws DocumentException, IOException {
        Font font = createFont(22, Font.BOLD);
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 设置标题下的时间字段
     *
     * @param time 时间
     * @return 时间的段落
     */
    private static Paragraph createHeadTime(String time) throws DocumentException, IOException {
        Font font = createFont(14, Font.BOLD);
        Paragraph paragraph = new Paragraph(time, font);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 设置一级标题
     *
     * @param title 标题内容
     * @return 标题段落
     */
    public static Paragraph createHead2(String title) throws DocumentException, IOException {
        Font font = createFont(12, Font.BOLD);
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 根据传入的标题名称：批量设置标题值
     *
     * @param table        创建的表格对象
     * @param tableHeadStr 每个标题值按顺序来
     */
    private static void createTableHead(PdfPTable table, String[] tableHeadStr) throws DocumentException, IOException {
        if (ObjectUtils.isEmpty(tableHeadStr)) {
            return;
        }
        //获取设置表格标题的字体
        Font font = createFont(10, Font.NORMAL);
        for (String tableHead : tableHeadStr) {
            PdfPCell cell = new PdfPCell(new Phrase(tableHead, font));
            cell.setBackgroundColor(new BaseColor(221, 221, 221));
            cell.setMinimumHeight(20);
            cell.setUseAscender(true);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            table.addCell(cell);
        }
    }

    /**
     * 设置表格内容
     *
     * @param title 标题内容
     * @return 表格标题内容
     */
    private static PdfPCell createTableContent(String title) throws DocumentException, IOException {
        Font font = createFont(10, Font.NORMAL);
        PdfPCell cell = new PdfPCell(new Phrase(title, font));
        cell.setMinimumHeight(20);
        cell.setUseAscender(true);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        return cell;
    }

    /**
     * 创建产品净值表格
     *
     * @param document         文档
     * @param tableContentList 表格数据
     * @throws DocumentException 异常信息
     * @throws IOException       异常信息
     */
    public static void buildProductNetValue(Document document, List<VehicleIndex1> tableContentList) throws DocumentException, IOException {
        //二级标题
        String title = "产品净值";
        Paragraph paragraphHead = createHead2(title);
        //设置段落前后间距
        paragraphHead.setSpacingAfter(10);
        paragraphHead.setSpacingBefore(10);
        document.add(paragraphHead);
        //创建表格(2列的表格)
        PdfPTable table = new PdfPTable(2);
        table.setTotalWidth(PageSize.A4.getWidth() - 100);
        table.setLockedWidth(true);
        // 创建头
        String[] tableHeadStr = {"单位净值", "累计净值"};
        createTableHead(table, tableHeadStr);
        // 添加表格内容
        createTableContent(table, tableContentList, null, null, null);
        document.add(table);
    }

    /**
     * 收益率指标表格
     *
     * @param document         文档
     * @param tableContentList 表格数据
     * @throws DocumentException 异常信息
     * @throws IOException       异常信息
     */
    public static void buildYield(Document document, List<VehicleIndex2> tableContentList) throws DocumentException, IOException {
        //二级标题
        String title = "收益率指标";
        Paragraph paragraphHead = createHead2(title);
        //设置段落前后间距
        paragraphHead.setSpacingAfter(10);
        paragraphHead.setSpacingBefore(10);
        document.add(paragraphHead);
        //创建表格(3列的表格)
        PdfPTable table = new PdfPTable(3);
        table.setTotalWidth(PageSize.A4.getWidth() - 100);
        table.setLockedWidth(true);
        // 创建头
        String[] tableHeadStr2 = {"", "本产品", "沪深300"};
        createTableHead(table, tableHeadStr2);
        createTableContent(table, null, tableContentList, null, null);
        document.add(table);
    }


    /**
     * 风险指标
     *
     * @param document         文档
     * @param tableContentList 表格数据
     * @throws DocumentException 异常信息
     * @throws IOException       异常信息
     */
    public static void buildRiskIndicator(Document document, List<VehicleIndex3> tableContentList) throws DocumentException, IOException {
        //二级标题
        String title = "风险指标";
        Paragraph paragraphHead = createHead2(title);
        //设置段落前后间距
        paragraphHead.setSpacingAfter(10);
        paragraphHead.setSpacingBefore(10);
        document.add(paragraphHead);
        //创建表格(3列的表格)
        PdfPTable table = new PdfPTable(2);
        table.setTotalWidth(PageSize.A4.getWidth() - 100);
        table.setLockedWidth(true);
        createTableContent(table, null, null, tableContentList, null);
        document.add(table);
    }

    /**
     * 产品信息
     *
     * @param document         文档
     * @param tableContentList 表格数据
     * @throws DocumentException 异常信息
     * @throws IOException       异常信息
     */
    public static void buildProductDetail(Document document, List<VehicleIndex3> tableContentList) throws DocumentException, IOException {
        //二级标题
        String title = "产品信息";
        Paragraph paragraphHead5 = createHead2(title);
        //设置段落前后间距
        paragraphHead5.setSpacingAfter(10);
        paragraphHead5.setSpacingBefore(10);
        document.add(paragraphHead5);
        PdfPTable table = new PdfPTable(2);
        table.setTotalWidth(PageSize.A4.getWidth() - 100);
        table.setLockedWidth(true);
        createTableContent(table, null, null, null, tableContentList);
        document.add(table);
    }

    /**
     * 创建表格内容
     *
     * @param table            表格对象
     * @param tableContentList 表格内容对象
     */
    private static void createTableContent(PdfPTable table, List<VehicleIndex1> tableContentList,
                                           List<VehicleIndex2> tableContentList2,
                                           List<VehicleIndex3> tableContentList3,
                                           List<VehicleIndex3> tableContentList4) throws DocumentException, IOException {
        //产品净值
        if (CollectionUtils.isNotEmpty(tableContentList)) {
            for (VehicleIndex1 vehicleIndex : tableContentList) {
                //获取设置表格内容的字体与内容
                table.addCell(createTableContent(vehicleIndex.getIndexValue()));
                table.addCell(createTableContent(vehicleIndex.getChainValue()));
            }
        }
        //收益率指标
        if (CollectionUtils.isNotEmpty(tableContentList2)) {
            for (VehicleIndex2 vehicleIndex : tableContentList2) {
                //获取设置表格内容的字体与内容
                table.addCell(createTableContent(vehicleIndex.getIndexName()));
                table.addCell(createTableContent(vehicleIndex.getIndexValue()));
                table.addCell(createTableContent(vehicleIndex.getChainValue()));
            }
        }
        //风险指标
        if (CollectionUtils.isNotEmpty(tableContentList3)) {
            for (VehicleIndex3 vehicleIndex : tableContentList3) {
                //获取设置表格内容的字体与内容
                table.addCell(createTableContent(vehicleIndex.getIndexName()));
                table.addCell(createTableContent(vehicleIndex.getIndexValue()));
            }
        }
        //产品信息
        if (CollectionUtils.isNotEmpty(tableContentList4)) {
            for (VehicleIndex3 vehicleIndex : tableContentList4) {
                //获取设置表格内容的字体与内容
                table.addCell(createTableContent(vehicleIndex.getIndexName()));
                table.addCell(createTableContent(vehicleIndex.getIndexValue()));
            }
        }
    }
}
