package com.xinyilu.system.checkreport;

import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
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.constant.Constants;
import com.xinyilu.common.utils.jreechart.FreeChartUtil;
import com.xinyilu.common.utils.jreechart.GenerateBarChartUtil;
import com.xinyilu.common.utils.jreechart.GenerateStackedBarChartUtil;
import com.xinyilu.system.domain.testLevel.TestItemLevel;
import com.xinyilu.system.domain.vo.BodyShapeAnalysisVO;
import com.xinyilu.system.domain.vo.TestBodyScoreInfoVO;
import com.xinyilu.system.domain.vo.childrenRanking.ChildrenRankingVO;
import com.xinyilu.system.domain.vo.childrenRanking.ItemScoreInfoVO;
import com.xinyilu.system.domain.vo.physiqueAnalysis.PhysiqueAnalysisVO;
import com.xinyilu.system.domain.vo.physiqueAnalysis.PhysiqueCategoryVO;
import com.xinyilu.system.domain.vo.testActionDevelopment.TestActionDevelopmentVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CenterTextMode;
import org.jfree.chart.plot.RingPlot;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.List;
import java.util.*;

/**
 * @Description 幼儿个人检测报告工具类
 * @Author 纪寒
 * @Date 2022-09-23 16:18:11
 * @Version 1.0
 */
@Component
@Slf4j
public class GenerateStudentCheckReport {

    /**
     * 学生基本信息标题
     */
    private static final String STUDENT_HEAD_TITLE = "学生基本信息";

    /**
     * 学生综合得分标题
     */
    private static final String COMPREHENSIVE_HEAD_TITLE = "综合得分";

    /**
     * 综合体质分析图标题
     */
    private static final String ANALYSIS_PICTURE_HEAD_TITLE = "综合体质分析图";

    /**
     * 综合得分字符串长度
     */
    private static final int LENGTH = 3;

    /**
     * 综合体质分析图标题
     */
    private static final String BODY_SHAPE_TITLE = "身体形态测试分析";

    /**
     * 综合体质分析图标题
     */
    private static final String HEIGHT_WEIGHT_TITLE = "身高体重信息";

    /**
     * 年龄身高比图形标题
     */
    private static final String AGE_HEIGHT_WEIGHT_TITLE = "年龄身高比和体重身高图";

    /**
     * BMI标题
     */
    private static final String BMI_TITLE = "BMI指标图";

    /**
     * 身体素质测试分析标题
     */
    private static final String PHYSICAL_SUBSTANCE_TITLE = "身体素质测试分析";

    /**
     * 测试项目文本类型值
     */
    private static final Long ITEM_TEXT_TYPE = 38L;

    /**
     * 测试项目数字类型值
     */
    private static final Long ITEM_NUMBER_TYPE = 37L;

    /**
     * 动作发展检测分析标题
     */
    private static final String ACTION_DEVELOP_TITLE = "动作发展分析";

    /**
     * 动作发展检测分析标题
     */
    private static final String CHILDREN_RANKING_TITLE = "综合体质分析";

    /**
     * 动作发展检测分析二级标题
     */
    private static final String TEST_ITEM_CONTRAST_TITLE = "体测项目分值与全校、全市对比";

    /**
     * 创建学生检测报告
     *
     * @param outputStream              文件输出流
     * @param physiqueAnalysis          学生个人综合分析数据
     * @param bodyShapeAnalysis         学生身体形态测试分析数据
     * @param physicalSubstanceTestList 学生身体素质测试分析数据
     * @param actionDevelopTestList     学生动作发展检测信息数据
     * @param childrenRankingTestInfo   学生综合体质分析数据
     * @throws Exception 异常信息
     */
    public static void createStudentCheckReport(ByteArrayOutputStream outputStream, PhysiqueAnalysisVO physiqueAnalysis,
                                                BodyShapeAnalysisVO bodyShapeAnalysis,
                                                List<TestBodyScoreInfoVO> physicalSubstanceTestList,
                                                List<TestActionDevelopmentVO> actionDevelopTestList,
                                                ChildrenRankingVO childrenRankingTestInfo) throws Exception {
        log.info("开始生成测试批次报告，批次编号为：{}", physiqueAnalysis.getBatchCode());
        Document document = new Document();
        document.setPageSize(PageSize.A4);
        document.setMargins(50, 50, 50, 50);
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);
        //设置图片是否错乱问题
        writer.setStrictImageSequence(true);
        String title = Constants.STUDENT_CHECK_REPORT_NAME;
        //打开文档，只有打开后才能往里面加东西
        document.open();
        //设置标题和主题
        document.addAuthor(Constants.STUDENT_CHECK_REPORT_AUTHOR);
        document.addCreator(Constants.STUDENT_CHECK_REPORT_CREATOR);
        document.addSubject(title);
        document.addTitle(title);
        //设置报告开头的标题和创建时间
        Paragraph titleParagraph = createFirstHead(title);
        document.add(titleParagraph);
        //设置学生基本信息
        setStudentInfo(document, physiqueAnalysis);
        //幼儿综合得分
        setComprehensiveScore(document, physiqueAnalysis);
        //综合体质分析图
        createPhysiqueAnalysisPicture(document, physiqueAnalysis);
        //设置身体形态才基本信息
        setStudentBodyShapeInfo(document, bodyShapeAnalysis);
        //身高体重柱状图
        createWeightAndHeightPicture(document, bodyShapeAnalysis);
        //BMI展示图
        createBmiPicture(document, bodyShapeAnalysis);
        //身体素质分析
        physicalSubstanceTestInfo(document, physicalSubstanceTestList);
        //动作发展检测信息
        setActionDevelopTestInfo(document, actionDevelopTestList);
        //综合体质分析
        setChildrenRankingTestInfo(document, childrenRankingTestInfo);
        document.close();
        writer.close();
        log.info("报告生成完成，批次编号为：{}", physiqueAnalysis.getBatchCode());
    }

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

    /**
     * 设置学生基本信息
     *
     * @param document         文档对象
     * @param physiqueAnalysis 学生个人综合分析数据信息
     */
    private static void setStudentInfo(Document document, PhysiqueAnalysisVO physiqueAnalysis) throws Exception {
        //二级标题
        Paragraph studentInfoTitleParagraph = createHeadInfo(STUDENT_HEAD_TITLE);
        document.add(studentInfoTitleParagraph);
        //基本信息
        Font font = createFont(12, Font.NORMAL);
        String studentName = StringUtils.isBlank(physiqueAnalysis.getStudentName()) ? "" : physiqueAnalysis.getStudentName();
        String studentSex = StringUtils.isBlank(physiqueAnalysis.getStudentSex()) ? "" : physiqueAnalysis.getStudentSex();
        double studentAge = Objects.isNull(physiqueAnalysis.getStudentAge()) ? 0 : physiqueAnalysis.getStudentAge();
        String kindergartenName = StringUtils.isBlank(physiqueAnalysis.getKindergartenName()) ? "" : physiqueAnalysis.getKindergartenName();
        String className = StringUtils.isBlank(physiqueAnalysis.getClassName()) ? "" : physiqueAnalysis.getClassName();
        String kindergartenAddress = StringUtils.isBlank(physiqueAnalysis.getKindergartenAddress()) ? "" : physiqueAnalysis.getKindergartenAddress();
        String info = "姓名：" + studentName + "  性别：" + studentSex + "  年龄："
                + studentAge + " 岁\n\n" + "所属幼儿园：" + kindergartenName + "  班级："
                + className + "\n\n" + "地址：" + kindergartenAddress;
        Paragraph studentInfoParagraph = new Paragraph(info, font);
        studentInfoParagraph.setSpacingAfter(10);
        studentInfoParagraph.setSpacingBefore(10);
        studentInfoParagraph.setAlignment(Element.ALIGN_CENTER);
        document.add(studentInfoParagraph);
    }

    /**
     * 设置综合得分
     *
     * @param document 文档对象
     * @throws Exception 异常信息
     */
    private static void setComprehensiveScore(Document document,
                                              PhysiqueAnalysisVO physiqueAnalysisVO) throws Exception {
        //设置综合得分标题
        Paragraph studentInfoTitleParagraph = createHeadInfo(COMPREHENSIVE_HEAD_TITLE);
        document.add(studentInfoTitleParagraph);
        //设置综合得分成绩
        if (CollectionUtils.isNotEmpty(physiqueAnalysisVO.getFirstItemCategoryList())) {
            //每个分类的得分信息
            StringBuilder comprehensiveScore = new StringBuilder();
            for (PhysiqueCategoryVO categoryVO : physiqueAnalysisVO.getFirstItemCategoryList()) {
                String categoryName = StringUtils.isBlank(categoryVO.getCategoryName()) ? "" : categoryVO.getCategoryName();
                BigDecimal categoryScore = Objects.isNull(categoryVO.getCategoryScore()) ? BigDecimal.ZERO : categoryVO.getCategoryScore();
                comprehensiveScore.append(categoryName).append("(").append(categoryScore).append(")").append("   +  ");
            }
            String comprehensiveScoreStr = "";
            if (comprehensiveScore.length() >= LENGTH) {
                comprehensiveScoreStr = comprehensiveScore.toString().substring(0, comprehensiveScore.toString().length() - 3) + "  =   综合得分(" + physiqueAnalysisVO.getTotalCategoryScore() + ")";
            }
            Font font = createFont(12, Font.NORMAL);
            Paragraph comprehensiveParagraph = new Paragraph(comprehensiveScoreStr, font);
            comprehensiveParagraph.setSpacingAfter(10);
            comprehensiveParagraph.setSpacingBefore(10);
            comprehensiveParagraph.setAlignment(Element.ALIGN_CENTER);
            document.add(comprehensiveParagraph);
        }
    }

    /**
     * 生成学生个人综合分析雷达图
     *
     * @param document         文本对象
     * @param physiqueAnalysis 个人分析数据
     * @throws Exception 异常信息
     */
    private static void createPhysiqueAnalysisPicture(Document document, PhysiqueAnalysisVO physiqueAnalysis) throws Exception {
        //设置综合体质分析图标题
        Paragraph analysisTitleParagraph = createHeadInfo(ANALYSIS_PICTURE_HEAD_TITLE);
        document.add(analysisTitleParagraph);
        //生成综合分析体质雷达图
        if (CollectionUtils.isNotEmpty(physiqueAnalysis.getPhysiqueCategoryList())) {
            //设置数据
            DefaultCategoryDataset dataset = new DefaultCategoryDataset();
            for (PhysiqueCategoryVO categoryVO : physiqueAnalysis.getPhysiqueCategoryList()) {
                //分类名称
                String categoryName = StringUtils.isBlank(categoryVO.getCategoryName()) ? "无" : categoryVO.getCategoryName();
                //分类分类级别描述
                String levelName = StringUtils.isBlank(categoryVO.getLevelName()) ? "无" : categoryVO.getLevelName();
                //得分
                BigDecimal categoryScore = Objects.isNull(categoryVO.getCategoryScore()) ? BigDecimal.ZERO : categoryVO.getCategoryScore();
                dataset.addValue(categoryScore.doubleValue(), categoryName, categoryScore + " (" + levelName + ")");
            }
            //创建雷达图并将雷达图写入到PDF文档中
            SpiderWebPlot spiderwebplot = new SpiderWebPlot(dataset);
            LegendTitle legendtitle = new LegendTitle(spiderwebplot);
            legendtitle.setPosition(RectangleEdge.TOP);
            JFreeChart chart = new JFreeChart(ANALYSIS_PICTURE_HEAD_TITLE, TextTitle.DEFAULT_FONT, spiderwebplot, false);
            chart.addSubtitle(legendtitle);
            savePictureToDocument(document, chart);
        }
    }

    /**
     * 设置身体形态测试和身高体重信息
     *
     * @param document          文档对象
     * @param bodyShapeAnalysis 身体形态测试数据信息
     */
    private static void setStudentBodyShapeInfo(Document document, BodyShapeAnalysisVO bodyShapeAnalysis) throws Exception {
        //身体形态测试标题
        Paragraph bodyShapeParagraph = createHeadInfo(BODY_SHAPE_TITLE);
        document.add(bodyShapeParagraph);
        //设置身体形态测试描述信息
        String bodyShapeInfo = StringUtils.isBlank(bodyShapeAnalysis.getShapeDescription()) ? "" : bodyShapeAnalysis.getShapeDescription();
        createTextInfo(document, bodyShapeInfo);
        //身高体重基本标题
        Paragraph weightAndHeightParagraph = createThreeHeadInfo(HEIGHT_WEIGHT_TITLE);
        document.add(weightAndHeightParagraph);
        //身高体重基本信息
        String heightAndWeightInfo = "姓名：" + bodyShapeAnalysis.getStudentName() + "   身高：" + bodyShapeAnalysis.getHeightScore()
                + bodyShapeAnalysis.getHeightMeasureUnit() + "   体重：" + bodyShapeAnalysis.getWeightScore()
                + bodyShapeAnalysis.getWeightMeasureUnit() + "   BMI：" + bodyShapeAnalysis.getBmi();
        createTextInfo(document, heightAndWeightInfo);
    }

    /**
     * 创建年龄身高比和年龄体重比柱状图
     *
     * @param document          文本对象
     * @param bodyShapeAnalysis 数据信息
     * @throws Exception 异常信息
     */
    private static void createWeightAndHeightPicture(Document document, BodyShapeAnalysisVO bodyShapeAnalysis) throws Exception {
        if (Objects.nonNull(bodyShapeAnalysis)) {
            Paragraph bodyShapeParagraph = createThreeHeadInfo(AGE_HEIGHT_WEIGHT_TITLE);
            document.add(bodyShapeParagraph);
            //x轴名称列表
            String ageHeightName = "年龄身高比（标准：" + bodyShapeAnalysis.getAgeHeightMin() + "-" + bodyShapeAnalysis.getAgeHeightMax() + "）";
            String ageWeightName = "年龄体重比（标准：" + bodyShapeAnalysis.getAgeWeightMin() + "-" + bodyShapeAnalysis.getAgeWeightMax() + "）";
            List<String> xAxisNameList = new ArrayList<>(Arrays.asList("年龄身高比和体重身高比", ""));
            //图例名称列表
            List<String> legendNameList = new ArrayList<>(Arrays.asList(ageWeightName, ageHeightName));
            //数据集合
            List<List<Object>> dataList = Lists.newArrayList();
            dataList.add(new ArrayList<>(Arrays.asList(bodyShapeAnalysis.getWeightScore(), BigDecimal.ZERO)));
            dataList.add(new ArrayList<>(Arrays.asList(bodyShapeAnalysis.getHeightScore(), BigDecimal.ZERO)));
            JFreeChart chart = GenerateStackedBarChartUtil.createStackedBarChart(AGE_HEIGHT_WEIGHT_TITLE, legendNameList, xAxisNameList
                    , dataList, FreeChartUtil.createChartTheme("宋体"), "", "");
            savePictureToDocument(document, chart);
        }
    }

    /**
     * 创建BMI环形图
     *
     * @param document          文本对象
     * @param bodyShapeAnalysis 数据信息
     * @throws Exception 异常信息
     */
    private static void createBmiPicture(Document document, BodyShapeAnalysisVO bodyShapeAnalysis) throws Exception {
        if (CollectionUtils.isNotEmpty(bodyShapeAnalysis.getBmiItemLevel())) {
            Paragraph bodyShapeParagraph = createThreeHeadInfo(BMI_TITLE);
            document.add(bodyShapeParagraph);
            //使用JFreeChart生成BMI环形图
            DefaultPieDataset dataSet = new DefaultPieDataset();
            for (TestItemLevel itemLevel : bodyShapeAnalysis.getBmiItemLevel()) {
                String levelName = StringUtils.isBlank(itemLevel.getLevelName()) ? "" : itemLevel.getLevelName();
                BigDecimal levelMinScore = Objects.isNull(itemLevel.getLevelMinScore()) ? BigDecimal.ZERO : itemLevel.getLevelMinScore();
                BigDecimal levelMaxScore = Objects.isNull(itemLevel.getLevelMaxScore()) ? BigDecimal.ZERO : itemLevel.getLevelMaxScore();
                levelName = levelName + "(" + levelMinScore + "-" + levelMaxScore + ")";
                dataSet.setValue(levelName, levelMaxScore);
            }
            StandardChartTheme mChartTheme = new StandardChartTheme("CN");
            mChartTheme.setLargeFont(new java.awt.Font("黑体", java.awt.Font.BOLD, 14));
            mChartTheme.setExtraLargeFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 20));
            //应用主题样式
            ChartFactory.setChartTheme(mChartTheme);
            JFreeChart chart = ChartFactory.createRingChart(BMI_TITLE, dataSet, true, false, false);
            //图表
            RingPlot ringplot = (RingPlot) chart.getPlot();
            ringplot.setLabelFont(new java.awt.Font("宋体", java.awt.Font.BOLD, 14));
            ringplot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{1}"));
            //设置环形图中心文字
            String centerText = "得分：" + bodyShapeAnalysis.getBmi() + "(" + bodyShapeAnalysis.getBmiDescription() + ")";
            ringplot.setCenterTextMode(CenterTextMode.FIXED);
            ringplot.setCenterText(centerText);
            ringplot.setCenterTextFont(new java.awt.Font("宋体", java.awt.Font.BOLD, 14));
            ringplot.setSimpleLabels(true);
            //标题
            TextTitle texttitle = chart.getTitle();
            texttitle.setFont(new java.awt.Font("宋体", java.awt.Font.BOLD, 30));
            //图示
            LegendTitle legendtitle = chart.getLegend();
            legendtitle.setItemFont(new java.awt.Font("宋体", java.awt.Font.BOLD, 14));
            savePictureToDocument(document, chart);
            //创建空段落，解决图片和表格之间的覆盖问题
            Paragraph body = createEmptyHeadInfo();
            document.add(body);
        }
    }

    /**
     * 设置学生身体素质分析数据
     *
     * @param document                  文档对象
     * @param physicalSubstanceTestList 身体素质分析数据
     * @throws Exception 异常信息
     */
    private static void physicalSubstanceTestInfo(Document document,
                                                  List<TestBodyScoreInfoVO> physicalSubstanceTestList) throws Exception {
        if (CollectionUtils.isNotEmpty(physicalSubstanceTestList)) {
            //表头内容
            List<String> tableHeadList = Arrays.asList("身体素质测试", "测量值", "成绩级别", "综合评价");
            //创建表格头并设置表格头部元素信息
            PdfPTable physicalSubstanceTable = createTableInfo(document, PHYSICAL_SUBSTANCE_TITLE, 4, tableHeadList);
            //填充表格其余元素信息
            fillPhysicalSubstanceTableContent(physicalSubstanceTable, physicalSubstanceTestList);
            document.add(physicalSubstanceTable);
        }
    }

    /**
     * 设置学生动作检测发展数据
     *
     * @param document              文档对象
     * @param actionDevelopTestList 动作检测发展数据
     * @throws Exception 异常信息
     */
    private static void setActionDevelopTestInfo(Document document,
                                                 List<TestActionDevelopmentVO> actionDevelopTestList) throws Exception {

        if (CollectionUtils.isNotEmpty(actionDevelopTestList)) {
            //表头内容
            List<String> tableHeadList = Arrays.asList("测试分类", "测试项目", "动作技能总分", "统一最高得分",
                    "小班最高得分", "中班最高得分", "大班最高得分", "综合得分", "综合评价", "测试目的");
            //创建表格头并设置表格头部元素信息
            PdfPTable physicalSubstanceTable = createTableInfo(document, ACTION_DEVELOP_TITLE, 10, tableHeadList);
            //填充表格其余元素信息
            fillActionDevelopTableContent(physicalSubstanceTable, actionDevelopTestList);
            document.add(physicalSubstanceTable);
        }
    }

    /**
     * 设置学生综合体质分析数据信息
     *
     * @param document                文档对象
     * @param childrenRankingTestInfo 综合体质分析数据
     * @throws Exception 异常信息
     */
    private static void setChildrenRankingTestInfo(Document document,
                                                   ChildrenRankingVO childrenRankingTestInfo) throws Exception {
        //综合体质分析一级标题
        Paragraph childrenRankParagraph = createHeadInfo(CHILDREN_RANKING_TITLE);
        document.add(childrenRankParagraph);
        //二级标题
        Paragraph threadHeadParagraph = createThreeHeadInfo(TEST_ITEM_CONTRAST_TITLE);
        document.add(threadHeadParagraph);
        //设置学校排名，区域成绩排序，区域成绩占比
        int schoolRank = Objects.isNull(childrenRankingTestInfo.getSchoolRank()) ? 0 : childrenRankingTestInfo.getSchoolRank();
        int areaRank = Objects.isNull(childrenRankingTestInfo.getAreaRank()) ? 0 : childrenRankingTestInfo.getAreaRank();
        String areaRate = StringUtils.isBlank(childrenRankingTestInfo.getAreaProportion()) ? "" : childrenRankingTestInfo.getAreaProportion();
        String scoreRankInfo = "学校排名：" + schoolRank + "名   " + "区域成绩排名：" + areaRank + "名   " + "区域成绩占比： " + areaRate;
        createTextInfo(document, scoreRankInfo);
        //生成各测试项目成绩的对比图
        createChildrenRankBarPicture(document, childrenRankingTestInfo);
    }

    /**
     * 创建学生综合分析各测试项目成绩对比柱状图
     *
     * @param document        文档对象
     * @param childrenRanking 排序信息
     * @throws Exception 异常信息
     */
    private static void createChildrenRankBarPicture(Document document, ChildrenRankingVO childrenRanking) throws Exception {
        if (CollectionUtils.isNotEmpty(childrenRanking.getItemScoreList())) {
            for (ItemScoreInfoVO scoreInfoVO : childrenRanking.getItemScoreList()) {
                //x轴名称列表
                List<String> xAxisNameList = CollectionUtils.isEmpty(childrenRanking.getItemStudentList()) ? Lists.newArrayList() : childrenRanking.getItemStudentList();
                //图例名称列表
                List<String> legendNameList = CollectionUtils.isEmpty(childrenRanking.getItemStudentList()) ? Lists.newArrayList() : childrenRanking.getItemStudentList();
                BigDecimal itemScore = Objects.isNull(scoreInfoVO.getItemScore()) ? BigDecimal.ZERO : scoreInfoVO.getItemScore();
                BigDecimal schoolAvgScore = Objects.isNull(scoreInfoVO.getSchoolAvgScore()) ? BigDecimal.ZERO : scoreInfoVO.getSchoolAvgScore();
                BigDecimal cityAvgScore = Objects.isNull(scoreInfoVO.getCityAvgScore()) ? BigDecimal.ZERO : scoreInfoVO.getCityAvgScore();
                String itemName = StringUtils.isBlank(scoreInfoVO.getItemName()) ? "" : scoreInfoVO.getItemName();
                //数据集合
                List<Object> dataList = Arrays.asList(itemScore, schoolAvgScore, cityAvgScore);
                //图例背景颜色
                List<Color> legendColorList = new ArrayList<>(Collections.singletonList(new Color(248, 99, 134)));
                List<BigDecimal> scoreList = Arrays.asList(itemScore, schoolAvgScore, cityAvgScore);
                BigDecimal maxScore = BigDecimal.ZERO;
                if (CollectionUtils.isNotEmpty(scoreList)) {
                    maxScore = Collections.max(scoreList);
                }
                JFreeChart chart = GenerateBarChartUtil.createSimpleBarChart(itemName, legendNameList, xAxisNameList
                        , dataList, FreeChartUtil.createChartTheme("宋体"), "", "",
                        0d, maxScore.doubleValue(), legendColorList, true, "{2}");
                savePictureToDocument(document, chart);
            }
        }
    }

    /**
     * 二级标题
     *
     * @param headTitle 二级标题名称
     * @return 时间的段落
     */
    private static Paragraph createHeadInfo(String headTitle) throws Exception {
        Font font = createFont(14, Font.BOLD);
        Paragraph paragraph = new Paragraph(headTitle, font);
        paragraph.setSpacingAfter(10);
        paragraph.setSpacingBefore(10);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 三级标题
     *
     * @param headTitle 三级标题名称
     * @return 时间的段落
     */
    private static Paragraph createThreeHeadInfo(String headTitle) throws Exception {
        Font font = createFont(12, Font.NORMAL);
        Paragraph paragraph = new Paragraph(headTitle, font);
        paragraph.setSpacingAfter(10);
        paragraph.setSpacingBefore(10);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 创建文本段落信息
     *
     * @param document 文档对象
     * @param info     文本信息
     * @throws Exception 异常信息
     */
    private static void createTextInfo(Document document, String info) throws Exception {
        Font font = createFont(12, Font.NORMAL);
        Paragraph paragraph = new Paragraph(info, font);
        paragraph.setSpacingAfter(10);
        paragraph.setSpacingBefore(10);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        document.add(paragraph);
    }

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

    /**
     * 将JFreeChart生成的图片保存到PDF文档中公共方法
     *
     * @param document 文档对象
     * @param chart    图片对象
     * @throws Exception 异常信息
     */
    private static void savePictureToDocument(Document document, JFreeChart chart) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ChartUtils.writeChartAsJPEG(outputStream, chart, 800, 600);
        Image image = Image.getInstance(outputStream.toByteArray());
        image.setAlignment(Image.ALIGN_CENTER);
        image.scaleAbsolute(500, 300);
        document.add(image);
    }

    /**
     * 创建表格公共方法，包含创建表格所在文档段落，表格样式，表头以及表头内容设置
     *
     * @param document      文档对象
     * @param tableTitle    表格标题
     * @param numColumns    表格列数
     * @param tableHeadList 表头内容
     * @return table 表格对象
     * @throws Exception 异常信息
     */
    private static PdfPTable createTableInfo(Document document, String tableTitle, int numColumns, List<String> tableHeadList) throws Exception {
        Paragraph actionDevelopParagraph = createHeadInfo(tableTitle);
        document.add(actionDevelopParagraph);
        //创建表格对象并设置样式
        PdfPTable table = new PdfPTable(numColumns);
        table.setTotalWidth(PageSize.A4.getWidth() - 100);
        table.setLockedWidth(true);
        //创建表头并塞值
        createTableHead(table, tableHeadList);
        return table;
    }

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

    /**
     * 填充身体素质分析表格内容
     *
     * @param table         表格对象
     * @param tableHeadList 表格内容
     */
    private static void fillPhysicalSubstanceTableContent(PdfPTable table, List<TestBodyScoreInfoVO> tableHeadList) throws Exception {
        if (CollectionUtils.isNotEmpty(tableHeadList)) {
            for (TestBodyScoreInfoVO scoreInfo : tableHeadList) {
                //设置表格内容的字体与内容
                table.addCell(createTableContent(StringUtils.isBlank(scoreInfo.getItemName()) ? "" : scoreInfo.getItemName()));
                //设置成绩
                Long scoreDictId = Objects.isNull(scoreInfo.getScoreDictId()) ? 0L : scoreInfo.getScoreDictId();
                String itemScore = "";
                if (scoreDictId.equals(ITEM_NUMBER_TYPE)) {
                    itemScore = Objects.isNull(scoreInfo.getItemScore()) ? BigDecimal.ZERO.toString() : scoreInfo.getItemScore().toString();
                }
                if (scoreDictId.equals(ITEM_TEXT_TYPE)) {
                    itemScore = StringUtils.isBlank(scoreInfo.getScoreDictValue()) ? "" : scoreInfo.getScoreDictValue();
                }
                table.addCell(createTableContent(itemScore));
                table.addCell(createTableContent(StringUtils.isBlank(scoreInfo.getLeveName()) ? "" : scoreInfo.getLeveName()));
                table.addCell(createTableContent(StringUtils.isBlank(scoreInfo.getSyntheticalAssess()) ? "" : scoreInfo.getSyntheticalAssess()));
            }
        }
    }

    /**
     * 填充动作发展检测表格内容
     *
     * @param table                 表格对象
     * @param actionDevelopTestList 表格内容
     */
    private static void fillActionDevelopTableContent(PdfPTable table, List<TestActionDevelopmentVO> actionDevelopTestList)
            throws Exception {
        if (CollectionUtils.isNotEmpty(actionDevelopTestList)) {
            for (TestActionDevelopmentVO development : actionDevelopTestList) {
                //设置表格内容的字体与内容
                table.addCell(createTableContent(StringUtils.isBlank(development.getCategoryName()) ? "" : development.getCategoryName()));
                table.addCell(createTableContent(StringUtils.isBlank(development.getItemName()) ? "" : development.getItemName()));
                table.addCell(createTableContent(Objects.isNull(development.getItemFraction()) ? BigDecimal.ZERO.toString() : development.getItemFraction().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getUnifiedStandardScore()) ? BigDecimal.ZERO.toString() : development.getUnifiedStandardScore().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getSmallStandardScore()) ? BigDecimal.ZERO.toString() : development.getSmallStandardScore().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getMiddleStandardScore()) ? BigDecimal.ZERO.toString() : development.getMiddleStandardScore().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getLargeStandardScore()) ? BigDecimal.ZERO.toString() : development.getLargeStandardScore().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getItemScoreAll()) ? BigDecimal.ZERO.toString() : development.getItemScoreAll().toString()));
                table.addCell(createTableContent(Objects.isNull(development.getSyntheticalAssess()) ? "" : development.getSyntheticalAssess()));
                table.addCell(createTableContent(Objects.isNull(development.getRemark()) ? "" : development.getRemark()));
            }
        }
    }

    /**
     * 设置表格内容
     *
     * @param title 标题内容
     * @return 表格标题内容
     */
    private static PdfPCell createTableContent(String title) throws Exception {
        Font font = createFont(12, 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;
    }

    /**
     * 创建空的段落名称
     *
     * @return 时间的段落
     */
    private static Paragraph createEmptyHeadInfo() throws Exception {
        Font font = createFont(14, Font.BOLD);
        Paragraph paragraph = new Paragraph("", font);
        paragraph.setSpacingAfter(150);
        paragraph.setSpacingBefore(150);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }
}
