package com.qmth.distributed.print.business.util.pdf;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.pdf.PdfReader;
import com.qmth.distributed.print.business.bean.dto.*;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
import com.qmth.distributed.print.business.enums.ExamNumberStyleEnum;
import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
import com.qmth.distributed.print.business.service.*;
import com.qmth.distributed.print.business.util.GoogleBarCodeUtil;
import com.qmth.distributed.print.business.util.PdfUtil;
import com.qmth.teachcloud.common.bean.vo.FilePathVo;
import com.qmth.teachcloud.common.bean.vo.OriginalVo;
import com.qmth.teachcloud.common.bean.vo.PaperInfoVo;
import com.qmth.teachcloud.common.bean.vo.PrintPathVo;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicAttachment;
import com.qmth.teachcloud.common.entity.BasicPrintConfig;
import com.qmth.teachcloud.common.entity.BasicSemester;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.BasicAttachmentService;
import com.qmth.teachcloud.common.service.BasicSemesterService;
import com.qmth.teachcloud.common.service.FileUploadService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.ConvertUtil;
import com.qmth.teachcloud.common.util.ExamTaskUtil;
import com.qmth.teachcloud.common.util.FileUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 创建pdf util
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/4/14
 */
@Component
public class CreatePdfNewUtil {
    private final static Logger log = LoggerFactory.getLogger(CreatePdfNewUtil.class);

    @Resource
    private BasicAttachmentService basicAttachmentService;
    @Resource
    @Lazy
    private PrintCommonService printCommonService;
    @Resource
    private TeachcloudCommonService teachcloudCommonService;
    @Resource
    private ExamDetailService examDetailService;
    @Resource
    private ExamStudentService examStudentService;
    @Resource
    private BasicTemplateService basicTemplateService;
    @Resource
    private BasicSemesterService basicSemesterService;
    @Resource
    private ExamTaskService examTaskService;
    @Resource
    private ExamTaskDetailService examTaskDetailService;
    @Resource
    private ExamPrintPlanService examPrintPlanService;
    @Resource
    private BasicPrintConfigService basicPrintConfigService;
    @Resource
    private FileUploadService fileUploadService;

    /**
     * 创建登记表
     *
     * @param examDetail
     * @param basicAttachment
     * @param printCount
     * @param fileTempList
     * @throws Exception
     */
    public void createCheckIn(ExamDetail examDetail, BasicAttachment basicAttachment, Integer printCount, List<File> fileTempList) throws Exception {
        Optional.ofNullable(basicAttachment).orElseThrow(() -> ExceptionResultEnum.ATTACHMENT_IS_NULL.exception());

        String type = basicAttachment.getType();
        FilePathVo filePathVo = JSON.parseObject(basicAttachment.getPath(), FilePathVo.class);

        if (Objects.nonNull(type) && Objects.equals(type, SystemConstant.PDF_PREFIX)) {
            String filePath = filePathVo.getPath();
            PrintPathVo printPathVo = new PrintPathVo(ClassifyEnum.CHECK_IN, filePathVo.getUploadType(), filePathVo.getType(), filePath, basicAttachment.getMd5(), null, null);
            examDetail.setAttachmentPath(printCommonService.parseAttachmentPath(examDetail.getAttachmentPath(), printPathVo));

//            for (int i = 0; i < printCount; i++) {
//                ordinaryPdfList.add(new PdfDto(filePath, PageSizeEnum.A4, 0));
//            }
        } else {
            File htmlFileTemp = SystemConstant.getFileTempVar(SystemConstant.HTML_PREFIX);
            fileUploadService.downloadFile(basicAttachment.getId(), htmlFileTemp.getPath());
            BasicAttachment attachment = printCommonService.saveAttachmentPdfFromHtml(String.valueOf(basicAttachment.getId()), htmlFileTemp, examDetail.getCreateId(), null, fileTempList, PageSizeEnum.A4);
            FilePathVo filePathVo1 = JSON.parseObject(attachment.getPath(), FilePathVo.class);
            PrintPathVo printPathVo = new PrintPathVo(ClassifyEnum.CHECK_IN, filePathVo1.getUploadType(), filePathVo1.getType(), filePathVo1.getPath(), attachment.getMd5(), null, null);
            examDetail.setAttachmentPath(printCommonService.parseAttachmentPath(examDetail.getAttachmentPath(), printPathVo));
        }
    }


    /**
     * 生成卷袋贴
     *
     * @param templateId
     * @param schoolName
     * @param examDetail
     * @param examStudentList
     * @param backupCount
     * @param printCount
     * @param examDetailCourseList
     * @param examId
     */
    public void createPaperPackage(Long templateId, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, Integer backupCount, Integer printCount, List<ExamDetailCourse> examDetailCourseList, Long examId) {
        BasicTemplate basicTemplate = basicTemplateService.getById(templateId);
        if (Objects.isNull(basicTemplate)) {
            throw ExceptionResultEnum.ERROR.exception("印品数据有误");
        }

        JSONObject object = JSON.parseObject(basicTemplate.getDisplayRange());

        PdfPackageDto pdfPackageDto = new PdfPackageDto();
        pdfPackageDto.setTitle(schoolName);
        pdfPackageDto.setPackageNumber(examDetail.getPackageCode());

        boolean isTag = false;
        for (ExamDetailCourse detailCourse : examDetailCourseList) {
            ExamTask examTask = examTaskService.getByExamIdAndCourseCodeAndPaperNumber(examId, detailCourse.getCourseCode(), detailCourse.getPaperNumber());
            ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamTaskId(examTask.getId());
            List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
            for (PaperInfoVo paperInfoVo : paperInfoVoList) {
                int pages = paperInfoVo.getPages();
                isTag = pages > 2;
                pdfPackageDto.setTag(isTag);
                if (isTag) {
                    break;
                }
            }
        }

        // 标题信息
        List<JSONObject> objectTitleList = JSON.parseArray(object.getString("title"), JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());
        List<Map<String, String>> titlePlate = new ArrayList<>();
        for (JSONObject jsonObject : objectTitleList) {
            Map<String, String> titleMap = new HashMap<>();
            String code = jsonObject.getString("code");
            String name = jsonObject.getString("name");
            titleMap.put("code", code);
            titleMap.put("name", name);
            if ("semesterName".equals(code)) {
                BasicSemester basicSemester = basicSemesterService.selectByExamId(examId);
                titleMap.put("value", basicSemester == null ? null : basicSemester.getName() + "  课程考试");
            }
            titlePlate.add(titleMap);
        }
        pdfPackageDto.setTitlePlate(titlePlate);

        List<JSONObject> objectList = JSON.parseArray(object.getString("basic"), JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());

        boolean isCourseHasTwo = objectList.stream().filter(m -> "courseCode".equals(m.getString("code")) || "courseName".equals(m.getString("code"))).count() == 2;
        boolean isDateHasTwo = objectList.stream().filter(m -> "examDate".equals(m.getString("code")) || "examTime".equals(m.getString("code"))).count() == 2;
        boolean isCourseFill = false;
        boolean isDateFill = false;
        // 基础信息
        List<Map<String, String>> basicPlate = new ArrayList<>();
        for (JSONObject jsonObject : objectList) {
            String code = jsonObject.getString("code");
            String name = jsonObject.getString("name");
            if ("examDate".equals(code) || "examTime".equals(code)) {
                String startDate = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DATE_PATTERN);
                String endDate = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DATE_PATTERN);
                String startTime = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.TIME_PATTERN);
                String endTime = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.TIME_PATTERN);
                Map<String, String> basicMap = new HashMap<>();
                if (isDateHasTwo) {
                    if (isDateFill) {
                        continue;
                    }
                    String examTime;
                    if (startDate.equals(endDate)) {
                        examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endTime;
                    } else {
                        examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endDate + " " + endTime;
                    }
                    basicMap.put("code", "examTime");
                    basicMap.put("name", "考试时间");
                    basicMap.put("value", examTime);
                    isDateFill = true;
                } else {
                    String examTime = "";
                    if ("examDate".equals(code)) {
                        if (startDate.equals(endDate)) {
                            examTime = startDate;
                        } else {
                            examTime = startDate + SystemConstant.HYPHEN + endDate;
                        }
                    } else if ("examTime".equals(code)) {
                        if (startDate.equals(endDate)) {
                            examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endTime;
                        } else {
                            examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endDate + " " + endTime;
                        }
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", examTime);
                }
                basicPlate.add(basicMap);
            } else if ("courseCode".equals(code) || "courseName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                if (isCourseHasTwo) {
                    if (isCourseFill) {
                        continue;
                    }
                    List<String> courseNames = examDetailCourseList.stream().map(m -> String.format("%s（%s）", m.getCourseName(), m.getCourseCode())).collect(Collectors.toList());
                    basicMap.put("code", "courseName");
                    basicMap.put("name", "课程名称");
                    basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, courseNames));
                    isCourseFill = true;
                } else {
                    List<String> courseNames = examDetailCourseList.stream().map(m -> "courseCode".equals(code) ? m.getCourseCode() : "courseName".equals(code) ? m.getCourseName() : "").collect(Collectors.toList());
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, courseNames));
                }
                basicPlate.add(basicMap);
            } else if ("paperNumber".equals(code)) {
                List<String> paperNumbers = examDetailCourseList.stream().map(ExamDetailCourse::getPaperNumber).collect(Collectors.toList());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, paperNumbers));
                basicPlate.add(basicMap);
            } else if ("examPlace".equals(code) || "campusName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", examDetail.getExamPlace());
                basicPlate.add(basicMap);
            } else if ("examRoom".equals(code) || "examClassroomName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", examDetail.getExamRoom());
                basicPlate.add(basicMap);
            } else if ("collegeName".equals(code)) {
                Set<String> collegeNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getCollegeName())).map(ExamStudent::getCollegeName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", CollectionUtils.isEmpty(collegeNames) ? "" : String.join(SystemConstant.COMMA_OF_CHINESE, collegeNames));
                basicPlate.add(basicMap);
            } else if ("majorName".equals(code)) {
                Set<String> stringSet = new HashSet<>();
                Set<String> majorNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getMajorName())).map(ExamStudent::getMajorName).collect(Collectors.toSet());
                if (!majorNames.isEmpty()) {
                    stringSet.addAll(majorNames);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", CollectionUtils.isEmpty(stringSet) ? "" : String.join(SystemConstant.COMMA_OF_CHINESE, stringSet));
                basicPlate.add(basicMap);
            } else if ("teachClazzName".equals(code)) {
                Set<String> stringSet = new HashSet<>();
                Set<String> teachClazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getTeachClazzName())).map(ExamStudentCourseDto::getTeachClazzName).collect(Collectors.toSet());
                if (!teachClazzNames.isEmpty()) {
                    stringSet.addAll(teachClazzNames);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", CollectionUtils.isEmpty(stringSet) ? "" : String.join(SystemConstant.COMMA_OF_CHINESE, stringSet));
                basicPlate.add(basicMap);
            } else if ("clazzName".equals(code)) {
                Set<String> stringSet = new HashSet<>();
                Set<String> clazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getClazzName())).map(ExamStudentCourseDto::getClazzName).collect(Collectors.toSet());
                if (!clazzNames.isEmpty()) {
                    stringSet.addAll(clazzNames);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", CollectionUtils.isEmpty(stringSet) ? "" : String.join(SystemConstant.COMMA_OF_CHINESE, stringSet));
                basicPlate.add(basicMap);
            } else if ("teacherName".equals(code)) {
                Set<String> stringSet = new HashSet<>();
                Set<String> teachNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getTeacherName())).map(ExamStudentCourseDto::getTeacherName).collect(Collectors.toSet());
                if (!teachNames.isEmpty()) {
                    stringSet.addAll(teachNames);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", CollectionUtils.isEmpty(stringSet) ? "" : String.join(SystemConstant.COMMA_OF_CHINESE, stringSet));
                basicPlate.add(basicMap);
            } else if ("paperCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", "paperCount");
                basicMap.put("name", "试卷数量");
                basicMap.put("value", examStudentList.size() + " + " + backupCount);
                basicPlate.add(basicMap);
            } else if ("examCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", "examCount");
                basicMap.put("name", "应考人数");
                basicMap.put("value", String.valueOf(examStudentList.size()));
                basicPlate.add(basicMap);
            } else if ("actualExamCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", "actualExamCount");
                basicMap.put("name", "实考人数");
                basicMap.put("value", "");
                basicPlate.add(basicMap);
            } else {
                // 扩展字段走本校验，进行数据组装
                Set<String> extendFieldsSet = examStudentList.stream().map(ExamStudentCourseDto::getExtendFields).collect(Collectors.toSet());
                Set<String> finalSet = new HashSet<>();
                for (String extendField : extendFieldsSet) {
                    List<JSONObject> jsonObjects = JSON.parseArray(extendField, JSONObject.class);
                    Set<String> values = jsonObjects.stream().filter(m -> code.equals(m.getString("code"))).map(m -> m.getString("value")).collect(Collectors.toSet());
                    finalSet.addAll(values);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, finalSet));
                basicPlate.add(basicMap);
            }
        }
        pdfPackageDto.setBasicPlate(basicPlate);
        printCommonService.saveAttachmentPackagePdf(pdfPackageDto, examDetail, printCount);
    }

    /**
     * 创建签到表
     *
     * @param templateId
     * @param schoolName
     * @param examDetail
     * @param examStudentList
     * @param printCount
     * @param examDetailCourseList
     */
    public void createSignBook(Long templateId, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, Integer printCount, List<ExamDetailCourse> examDetailCourseList) {
        BasicTemplate basicTemplate = basicTemplateService.getById(templateId);
        if (Objects.isNull(basicTemplate)) {
            throw ExceptionResultEnum.ERROR.exception("印品数据有误");
        }
        PdfSignDto pdfFillDto = new PdfSignDto();
        pdfFillDto.setTitle(schoolName + "签到表");
        pdfFillDto.setPackageNumber(examDetail.getPackageCode());
        pdfFillDto.setTextDesc(basicTemplate.getTextDesc());

        JSONObject jsonObject = JSON.parseObject(basicTemplate.getDisplayRange());
        List<JSONObject> objectList = JSON.parseArray(jsonObject.getString("basic"), JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());

        boolean isCourseHasTwo = objectList.stream().filter(m -> "courseCode".equals(m.getString("code")) || "courseName".equals(m.getString("code"))).count() == 2;
        boolean isDateHasTwo = objectList.stream().filter(m -> "examDate".equals(m.getString("code")) || "examTime".equals(m.getString("code"))).count() == 2;
        boolean isPlaceHasTwo = objectList.stream().filter(m -> "examPlace".equals(m.getString("code")) || "examRoom".equals(m.getString("code"))).count() == 2;

        // 基础信息
        List<Map<String, String>> basicPlate = new ArrayList<>();
        boolean isCourseFill = false;
        boolean isDateFill = false;
        boolean isPlaceFill = false;
        for (JSONObject object : objectList) {
            String code = object.getString("code");
            String name = object.getString("name");
            if ("courseCode".equals(code) || "courseName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                if (isCourseHasTwo) {
                    if (isCourseFill) {
                        continue;
                    }
                    List<String> courseNames = examDetailCourseList.stream().map(m -> String.format("%s（%s）", m.getCourseName(), m.getCourseCode())).collect(Collectors.toList());
                    basicMap.put("code", "courseName");
                    basicMap.put("name", "课程名称");
                    basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, courseNames));
                    isCourseFill = true;
                } else {
                    List<String> courseNames = examDetailCourseList.stream().map(m -> "courseCode".equals(code) ? m.getCourseCode() : "courseName".equals(code) ? m.getCourseName() : "").collect(Collectors.toList());
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, courseNames));
                }
                basicPlate.add(basicMap);
            } else if ("paperNumber".equals(code)) {
                List<String> paperNumbers = examDetailCourseList.stream().map(ExamDetailCourse::getPaperNumber).collect(Collectors.toList());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, paperNumbers));
                basicPlate.add(basicMap);
            } else if ("examDate".equals(code) || "examTime".equals(code)) {
                String startDate = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DATE_PATTERN);
                String endDate = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DATE_PATTERN);
                String startTime = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.TIME_PATTERN);
                String endTime = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.TIME_PATTERN);

                Map<String, String> basicMap = new HashMap<>();
                if (isDateHasTwo) {
                    if (isDateFill) {
                        continue;
                    }
                    String examTime;
                    if (startDate.equals(endDate)) {
                        examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endTime;
                    } else {
                        examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endDate + " " + endTime;
                    }
                    basicMap.put("code", "examTime");
                    basicMap.put("name", "考试时间");
                    basicMap.put("value", examTime);
                    isDateFill = true;
                } else {
                    String examTime = "";
                    if ("examDate".equals(code)) {
                        if (startDate.equals(endDate)) {
                            examTime = startDate;
                        } else {
                            examTime = startDate + SystemConstant.HYPHEN + endDate;
                        }
                    } else if ("examTime".equals(code)) {
                        if (startDate.equals(endDate)) {
                            examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endTime;
                        } else {
                            examTime = startDate + " " + startTime + SystemConstant.HYPHEN + endDate + " " + endTime;
                        }
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", examTime);
                }
                basicPlate.add(basicMap);
            } else if ("examPlace".equals(code) || "examRoom".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                if (isPlaceHasTwo) {
                    if (isPlaceFill) {
                        continue;
                    }
                    StringJoiner stringJoiner = new StringJoiner("");
                    if (StringUtils.isNotBlank(examDetail.getExamPlace())) {
                        stringJoiner.add(examDetail.getExamPlace());
                    }
                    if (StringUtils.isNotBlank(examDetail.getExamRoom())) {
                        stringJoiner.add(examDetail.getExamRoom());
                    }
                    basicMap.put("code", "examRoom");
                    basicMap.put("name", "考试地点");
                    basicMap.put("value", stringJoiner.toString());
                    isPlaceFill = true;
                } else {
                    StringJoiner stringJoiner = new StringJoiner("");
                    if ("examPlace".equals(code) && StringUtils.isNotBlank(examDetail.getExamPlace())) {
                        stringJoiner.add(examDetail.getExamPlace());
                    }
                    if ("examRoom".equals(code) && StringUtils.isNotBlank(examDetail.getExamRoom())) {
                        stringJoiner.add(examDetail.getExamRoom());
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", stringJoiner.toString());
                }
                basicPlate.add(basicMap);
            } else if ("collegeName".equals(code)) {
                Set<String> collegeNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getCollegeName())).map(ExamStudentCourseDto::getCollegeName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, collegeNames));
                basicPlate.add(basicMap);
            } else if ("majorName".equals(code)) {
                Set<String> majorNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getMajorName())).map(ExamStudentCourseDto::getMajorName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, majorNames));
                basicPlate.add(basicMap);
            } else if ("teachClazzName".equals(code)) {
                Set<String> teachClazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getTeachClazzName())).map(ExamStudentCourseDto::getTeachClazzName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, teachClazzNames));
                basicPlate.add(basicMap);
            } else if ("clazzName".equals(code)) {
                Set<String> clazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getClazzName())).map(ExamStudentCourseDto::getClazzName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, clazzNames));
                basicPlate.add(basicMap);
            } else if ("teacherName".equals(code)) {
                Set<String> teacherNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getTeacherName())).map(ExamStudentCourseDto::getTeacherName).collect(Collectors.toSet());
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, teacherNames));
                basicPlate.add(basicMap);
            } else if ("examCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.valueOf(examStudentList.size()));
                basicPlate.add(basicMap);
            } else if ("actualExamCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "");
                basicPlate.add(basicMap);
            } else {
                // 扩展字段走本校验，进行数据组装
                Set<String> extendFieldsSet = examStudentList.stream().map(ExamStudentCourseDto::getExtendFields).collect(Collectors.toSet());
                Set<String> finalSet = new HashSet<>();
                for (String extendField : extendFieldsSet) {
                    List<JSONObject> jsonObjects = JSON.parseArray(extendField, JSONObject.class);
                    Set<String> values = jsonObjects.stream().filter(m -> code.equals(m.getString("code"))).map(m -> m.getString("value")).collect(Collectors.toSet());
                    finalSet.addAll(values);
                }
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", String.join(SystemConstant.COMMA_OF_CHINESE, finalSet));
                basicPlate.add(basicMap);
            }
        }
        pdfFillDto.setBasicPlate(basicPlate);

        // 表头信息
        List<JSONObject> tableList = JSON.parseArray(jsonObject.getString("table"), JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());
        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
        for (JSONObject object : tableList) {
            studentHeadPlateMap.put(object.getString("code"), object.getString("name"));
        }
        studentHeadPlateMap.put("studentSign", "签名");
        pdfFillDto.setStudentHeadPlate(studentHeadPlateMap);

        // 考生信息
        List<Map<String, String>> studentPlate = new ArrayList<>();
        for (ExamStudentCourseDto examStudentCourseDto : examStudentList) {
            Map<String, String> studentMap = new LinkedHashMap<>();
            if (studentHeadPlateMap.containsKey("siteNumber")) {
                studentMap.put("siteNumber", examStudentCourseDto.getSiteNumber());
            }
            if (studentHeadPlateMap.containsKey("studentName")) {
                studentMap.put("studentName", examStudentCourseDto.getStudentName());
            }
            if (studentHeadPlateMap.containsKey("studentCode")) {
                studentMap.put("studentCode", examStudentCourseDto.getStudentCode());
            }
            if (studentHeadPlateMap.containsKey("courseName")) {
                studentMap.put("courseName", examStudentCourseDto.getCourseName());
            }
            if (studentHeadPlateMap.containsKey("teachClazzName")) {
                studentMap.put("teachClazzName", examStudentCourseDto.getTeachClazzName());
            }
            if (studentHeadPlateMap.containsKey("clazzName")) {
                studentMap.put("clazzName", examStudentCourseDto.getClazzName());
            }
            if (studentHeadPlateMap.containsKey("ticketNumber")) {
                studentMap.put("ticketNumber", examStudentCourseDto.getTicketNumber());
            }
            if (studentHeadPlateMap.containsKey("studentSign")) {
                studentMap.put("studentSign", "");
            }
            studentPlate.add(studentMap);
        }
        pdfFillDto.setStudentPlate(studentPlate);

        printCommonService.saveAttachmentSignPdf(pdfFillDto, examDetail, printCount, basicTemplate);
    }

    /**
     * 题卡html内容，所有参数置空
     *
     * @param htmlContent
     * @return
     */
    public String replaceBlankHtmlContent(String htmlContent) {
        // 替换条码参数
        htmlContent = htmlContent.replaceAll("<img src=\"data:image/png;base64,\\$\\{examNumber\\}\">", "");
        // 正则匹配所有参数，填入空值
        htmlContent = htmlContent.replaceAll("\\$\\{[A-Za-z0-9]+\\}", "");
        return htmlContent;

    }

    /**
     * 获取题卡attachmentId
     *
     * @param examCard
     * @param attachmentIds
     */
    public void getCardAttachmentId(ExamCard examCard, Set<Long> attachmentIds) {
        if (Objects.nonNull(examCard.getBackupAttachment()) && !Objects.equals("", examCard.getBackupAttachment())) {
            JSONObject jsonObjectCard = JSONObject.parseObject(examCard.getBackupAttachment());
            JSONArray jsonArrayCard = (JSONArray) jsonObjectCard.get("card");
            for (int i = 0; i < jsonArrayCard.size(); i++) {
                JSONObject object = (JSONObject) jsonArrayCard.get(i);
                if (Objects.nonNull(object.get("attachmentId")) && !Objects.equals("", object.get("attachmentId"))) {
                    attachmentIds.add((Long) (object.get("attachmentId")));
                }
            }
        }
    }

    /**
     * 获取试卷pdf
     *
     * @param stuPaperType   考生卷型
     * @param paperPdfDto    抽取的试卷文件信息
     * @param createPdfDto   生成pdf
     * @param waterMarkNames 水印内容
     */
    public PdfDto getExamStudentPaperPdf(String stuPaperType, List<PaperPdfDto> paperPdfDto, CreatePdfDto createPdfDto, String[] waterMarkNames) throws IOException {
        Set<Integer> pagesList = new HashSet<>();
        if (!CollectionUtils.isEmpty(paperPdfDto)) {
            for (PaperPdfDto dto : paperPdfDto) {
                if (stuPaperType.equals(dto.getType())) {
                    int pages = dto.getPages();
                    pagesList.add(pages);
                    PdfDto pdfDto = PdfUtil.addPdfPage(dto.getFile());
                    File file = paperPdfDto.size() > 1 ? PdfUtil.addWaterMark(dto.getFile(), waterMarkNames, 0.5f, 12, 0) : dto.getFile();
                    createPdfDto.getPaperPdfList().add(new PdfDto(file.getPath(), dto.getPageSize(), pdfDto.getPageCount()));
                }
            }
            int pageCount = pagesList.stream().mapToInt(Integer::intValue).sum();
            return new PdfDto(paperPdfDto.get(0).getPageSize(), pageCount);
        } else {
            return null;
        }
    }

    /**
     * 获取备份试卷pdf
     *
     * @param paperPdfDto  抽取的试卷文件信息
     * @param backupCount  备份数量
     * @param createPdfDto 生成pdf对象
     */
    public PdfDto getBackupPaperPdfList(List<PaperPdfDto> paperPdfDto, Integer backupCount, CreatePdfDto createPdfDto) throws
            IOException {
        Set<Integer> pagesList = new HashSet<>();
        boolean tag = false;
        if (CollectionUtils.isNotEmpty(paperPdfDto)) {
            for (PaperPdfDto dto : paperPdfDto) {
                int pages = dto.getPages();
                pagesList.add(pages);
                tag = pages > 2;
                PdfDto pdfDto = PdfUtil.addPdfPage(dto.getFile());
                for (int j = 1; j <= backupCount; j++) {
                    createPdfDto.getPaperPdfList().add(new PdfDto(dto.getFile().getPath(), dto.getPageSize(), pdfDto.getPageCount()));
                }
            }
            int pageCount = pagesList.stream().mapToInt(Integer::intValue).sum();
            return new PdfDto(paperPdfDto.get(0).getPageSize(), pageCount, tag);
        } else {
            return null;
        }
    }

    /**
     * 获取考试试卷
     *
     * @param paperType       抽取的试卷型（多个用,分隔）
     * @param paperInfoVoList 命题任务上传试卷信息
     */
    public List<PaperPdfDto> getPaperPdfFile(String paperType, List<PaperInfoVo> paperInfoVoList, CreatePdfDto createPdfDto) throws Exception {
        String[] paperTypes = paperType.split(",");
        List<PaperPdfDto> paperPdfDtoList = new ArrayList<>();
        PaperPdfDto paperPdfDto;
        for (PaperInfoVo paperInfoVo : paperInfoVoList) {
            BasicAttachment basicAttachment = basicAttachmentService.getById(paperInfoVo.getAttachmentId());
            Optional.ofNullable(basicAttachment).orElseThrow(() -> ExceptionResultEnum.ATTACHMENT_IS_NULL.exception("命题任务中上传试卷文件路径不存在"));

            // 卷型
            String name = paperInfoVo.getName();
            OriginalVo original = paperInfoVo.getOriginal();
            // 返回抽中的试卷
            for (String type : paperTypes) {
                if (StringUtils.equalsIgnoreCase(name, type)) {
                    File file = SystemConstant.getFileTempVar(SystemConstant.PDF_PREFIX);
                    createPdfDto.getFileTempList().add(file);
                    fileUploadService.downloadFile(basicAttachment, file.getPath());
//                    PageSizeEnum pageSizeEnum = PageSizeEnum.valueOf(original.getPageSize());
//                    Optional.ofNullable(pageSizeEnum).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("命题任务中上传试卷文件未设置pdf格式"));
                    paperPdfDto = new PaperPdfDto(type, file, new PdfReader(new FileInputStream(file)).getNumberOfPages(), null);
                    paperPdfDtoList.add(paperPdfDto);
                    break;
                }
            }
        }
        return paperPdfDtoList;
    }

    private String randomPaperType(String[] unexposedPaperTypes, int drawCount) {
        List<String> finalTypes = new ArrayList<>();
        List<String> unexposedPaperTypesList = new ArrayList<>(Arrays.asList(unexposedPaperTypes));
        for (int i = 0; i < drawCount; i++) {
            int index = new Random().nextInt(unexposedPaperTypesList.size());
            finalTypes.add(unexposedPaperTypesList.get(index));
            unexposedPaperTypesList.remove(index);
        }

        finalTypes = finalTypes.stream().sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
        return String.join(",", finalTypes);
    }

    /**
     * 合并A3 pdf
     *
     * @param list
     * @return
     * @throws IOException
     */
    public String mergeA3Pdf(List<PdfDto>... list) {
        List<PdfDto> mergePdfA3List = new ArrayList<>();
        for (int i = 0; i < list.length; i++) {
            mergePdfA3List.addAll(list[i]);
        }
        List<String> pathA3List = mergePdfA3List.stream().map(PdfDto::getPath).collect(Collectors.toList());
        return PdfUtil.mergePdf(pathA3List.toArray(new String[mergePdfA3List.size()]), null);
    }

    /**
     * 合并A4 pdf
     *
     * @param list
     * @return
     * @throws IOException
     */
    public String mergeA4Pdf(List<File> fileTempList, List<PdfDto>... list) {
        List<PdfDto> mergePdfA4List = new ArrayList<>();
        for (int i = 0; i < list.length; i++) {
            mergePdfA4List.addAll(list[i]);
        }
        List<String> pathA4List = mergePdfA4List.stream().map(PdfDto::getPath).collect(Collectors.toList());
        return PdfUtil.mergePdf(pathA4List.toArray(new String[mergePdfA4List.size()]), null, fileTempList);
    }

    /**
     * 合并pdf后保存数据库
     *
     * @param dirNamePaper
     * @param dirNameCardA3
     * @param tbTaskPdf
     * @return
     * @throws Exception
     */
    @Transactional
    public void mergePdfSaveDb(String dirNamePaper,
                               String dirNameCardA3,
                               TBTaskPdf tbTaskPdf) throws Exception {
        ExamDetail examDetail = examDetailService.getById(tbTaskPdf.getId());
        BasicPrintConfig basicPrintConfig = basicPrintConfigService.getByExamId(tbTaskPdf.getExamId());
        // 试卷+题卡
        if (StringUtils.isNotBlank(dirNamePaper)) {
            File localPaperPdfFile = new File(FileUtil.replaceSplit(dirNamePaper));
            examDetail.setPaperPages(PdfUtil.getPdfPages(localPaperPdfFile));

            String uploadFileName = PdfUtil.md5FileName(CreatePdfTypeEnum.PAPER.name() + tbTaskPdf.getId()) + SystemConstant.PDF_PREFIX;
            FilePathVo filePathVo = fileUploadService.uploadFile(localPaperPdfFile, UploadFileEnum.PDF, uploadFileName);
            BasicAttachment basicAttachment = new BasicAttachment(JSON.toJSONString(filePathVo), localPaperPdfFile.getName(), SystemConstant.PDF_PREFIX, new BigDecimal(localPaperPdfFile.length()), filePathVo.getMd5(), tbTaskPdf.getCreateId());
            basicAttachmentService.save(basicAttachment);
            examDetail.setAttachmentId(basicAttachment.getId());
        }
        // 题卡
        if (StringUtils.isNotBlank(dirNameCardA3)) {
            File localA3PdfCardFile = new File(FileUtil.replaceSplit(dirNameCardA3));
            examDetail.setCardPages(PdfUtil.getPdfPages(localA3PdfCardFile));

            String uploadFileName = PdfUtil.md5FileName(CreatePdfTypeEnum.CARD_A3.name() + tbTaskPdf.getId()) + SystemConstant.PDF_PREFIX;
            FilePathVo filePathVo = fileUploadService.uploadFile(localA3PdfCardFile, UploadFileEnum.PDF, uploadFileName);
            BasicAttachment basicAttachment = new BasicAttachment(JSON.toJSONString(filePathVo), localA3PdfCardFile.getName(), SystemConstant.PDF_PREFIX, new BigDecimal(localA3PdfCardFile.length()), filePathVo.getMd5(), tbTaskPdf.getCreateId());
            basicAttachmentService.save(basicAttachment);
            examDetail.setCardAttachmentId(basicAttachment.getId());
        }
        if (PrintMethodEnum.AUTO == basicPrintConfig.getPrintMethod()) {
            examDetail.setStatus(ExamDetailStatusEnum.WAITING);
        } else {
            examDetail.setStatus(ExamDetailStatusEnum.READY);
        }
        examDetail.setNormal(true);
        examDetailService.saveOrUpdate(examDetail);

        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTaskPdf.getPrintPlanId());
        if (PrintMethodEnum.AUTO == basicPrintConfig.getPrintMethod()) {
            examPrintPlan.setStatus(PrintPlanStatusEnum.PRINTING);
            examPrintPlanService.updateById(examPrintPlan);
        }
    }

    /**
     * 考生题卡html
     *
     * @param studentHtml        题卡html内容
     * @param examStudent        考生对象
     * @param examDetail         考场对象
     * @param userId             当前用户ID
     * @param examStudentPdfList 考生题卡集合
     * @param fileTempList
     * @param basicCardRule      题卡规则
     */
    public BasicAttachment examStudentHtml(String studentHtml, ExamStudent examStudent, String paperType, ExamDetail examDetail,
                                           Long userId, List<PdfDto> examStudentPdfList, List<File> fileTempList, BasicCardRule basicCardRule) throws IOException {
        if (ExamNumberStyleEnum.PRINT.equals(basicCardRule.getExamNumberStyle())) {
            // 生成学生考号条码并将图片转成base64
            studentHtml = studentHtml.replaceAll("\\$\\{studentCodeBarcode\\}", examStudent != null && examStudent.getStudentCode() != null ? GoogleBarCodeUtil.createBarCode(examStudent.getStudentCode(), false) : "");
            studentHtml = studentHtml.replaceAll("\\$\\{ticketNumberBarcode\\}", examStudent != null && examStudent.getTicketNumber() != null ? GoogleBarCodeUtil.createBarCode(examStudent.getTicketNumber(), false) : "");
            studentHtml = studentHtml.replaceAll("\\$\\{examNumber\\}", examStudent != null && examStudent.getStudentCode() != null ? GoogleBarCodeUtil.createBarCode(examStudent.getStudentCode(), false) : "");
            studentHtml = studentHtml.replaceAll("\\$\\{examNumberStr\\}", examStudent != null && examStudent.getStudentCode() != null ? examStudent.getStudentCode() : "");
            // 随机生成学生试卷条码并将图片转成base64
            studentHtml = studentHtml.replaceAll("\\$\\{paperType\\}", examStudent != null && examStudent.getPaperType() != null ? GoogleBarCodeUtil.createBarCode(SystemConstant.convertPaperType(examStudent.getPaperType()), false) : StringUtils.isNotBlank(paperType) ? GoogleBarCodeUtil.createBarCode(SystemConstant.convertPaperType(paperType), false) : "");
            // 替换考生卷型
            studentHtml = studentHtml.replaceAll("\\$\\{paperTypeName\\}", examStudent != null && examStudent.getPaperType() != null ? examStudent.getPaperType() : StringUtils.isNotBlank(paperType) ? paperType : "");

            if (examStudent != null) {
                // 根据题卡规则必选字段，替换相应值，没有则“”
                List<StudentExtendDto> studentExtendDtos = createExtendObject(examDetail, examStudent, basicCardRule);
                if (studentExtendDtos != null) {
                    for (StudentExtendDto extendDto : studentExtendDtos) {
                        studentHtml = studentHtml.replaceAll("\\$\\{" + extendDto.getFieldName() + "\\}", String.valueOf(extendDto.getValue()));
                    }
                }
            }
        } else if (ExamNumberStyleEnum.FILL.equals(basicCardRule.getExamNumberStyle())) {
            String fillFields = basicCardRule.getFillFields();
            if (StringUtils.isNotBlank(fillFields)) {
                if (examStudent != null) {
                    // 根据题卡规则必选字段，替换相应值，没有则“”
                    List<StudentExtendDto> studentExtendDtos = createExtendObject(examDetail, examStudent, basicCardRule);
                    if (CollectionUtils.isNotEmpty(studentExtendDtos)) {
                        for (String s : fillFields.split(",")) {
                            Optional<StudentExtendDto> extendDto = studentExtendDtos.stream().filter(m -> m.getFieldName().equals(s)).findFirst();
                            if (extendDto.isPresent()) {
                                StudentExtendDto studentExtendDto = extendDto.get();
                                studentHtml = studentHtml.replaceAll("\\$\\{" + studentExtendDto.getFieldName() + "\\}", String.valueOf(studentExtendDto.getValue()));
                            }
                        }
                    }
                }
            }
        }

        studentHtml = studentHtml.replaceAll("\\$\\{packageCodeDom\\}", "");
        // 将其它未匹配到值的参数，填入空值
        studentHtml = studentHtml.replaceAll("\\$\\{[A-Za-z0-9]+\\}", "");
        //学生题卡
        BasicAttachment examStudentAttachment = printCommonService.saveAttachmentPdfFromHtml(examStudent != null ? examStudent.getId() + "|" + examStudent.getStudentCode() : SystemConstant.getNanoId(), studentHtml, userId, examStudentPdfList, fileTempList);
        if (examStudent != null) {
            examStudent.setAttachmentId(examStudentAttachment.getId());
        }
        return examStudentAttachment;
    }

    /**
     * 题卡规则字段
     *
     * @param examDetail
     * @param examStudent   考生对象
     * @param basicCardRule 题卡规则对象
     */
    private List<StudentExtendDto> createExtendObject(ExamDetail examDetail, ExamStudent examStudent, BasicCardRule
            basicCardRule) {
        ExamStudentPdfInfoDto examStudentPdfInfoDto = examStudent == null ? null : examStudentService.getByStudentId(examStudent.getId());
        if (basicCardRule == null) {
            return null;
        }
        List<JSONObject> requiredFieldsJson = JSONArray.parseArray(basicCardRule.getRequiredFields(), JSONObject.class);
        List<StudentExtendDto> studentExtendDtos = new ArrayList<>();
        if (requiredFieldsJson.size() > 0) {
            for (JSONObject jsonObject : requiredFieldsJson) {
                StudentExtendDto studentExtendDto = new StudentExtendDto();
                String code = String.valueOf(jsonObject.get("code"));
                studentExtendDto.setFieldName(code);
                Object value = examStudentPdfInfoDto == null ? null : ReflectUtil.getFieldValue(examStudentPdfInfoDto, code);
                studentExtendDto.setValue(value == null ? "" : value);
                studentExtendDtos.add(studentExtendDto);
            }
        }
        List<JSONObject> extendFieldsJson = JSONArray.parseArray(basicCardRule.getExtendFields(), JSONObject.class);
        if (extendFieldsJson.size() > 0) {
            Map<String, Object> studentExtendMap = null;
            if (examStudentPdfInfoDto != null && StringUtils.isNotBlank(examStudentPdfInfoDto.getExtendFields())) {
                studentExtendMap = JSONArray.parseArray(examStudentPdfInfoDto.getExtendFields(), JSONObject.class).stream().collect(Collectors.toMap(k -> String.valueOf(k.get("code")), v -> v.get("value")));
            }

            Map<String, Object> map = ConvertUtil.analyzeDateAndTime(examDetail.getExamStartTime(), examDetail.getExamEndTime());

            for (JSONObject jsonObject : extendFieldsJson) {
                boolean enable = Boolean.parseBoolean(jsonObject.get("enable").toString());
                StudentExtendDto studentExtendDto = new StudentExtendDto();
                String code = String.valueOf(jsonObject.get("code"));

                studentExtendDto.setFieldName(code);
                Object value = examStudentPdfInfoDto == null ? null : ReflectUtil.getFieldValue(examStudentPdfInfoDto, code);
                // 时间需要特殊处理
                if ("examDate".equals(code)) {
                    value = Objects.nonNull(map.get("date")) ? (String) map.get("date") : "";
                }
                if ("examTime".equals(code)) {
                    value = Objects.nonNull(map.get("time")) ? (String) map.get("time") : "";
                }
                if (value == null) {
                    value = studentExtendMap == null ? null : studentExtendMap.get(code);
                }
                studentExtendDto.setValue(value == null ? "" : value);
                studentExtendDtos.add(studentExtendDto);
            }
        }
        return studentExtendDtos;
    }

    /**
     * 题卡规则字段
     *
     * @param basicCardRule 题卡规则对象
     */
    private List<StudentExtendDto> createExtendObjectNull(BasicCardRule basicCardRule) {
        if (basicCardRule == null) {
            return null;
        }
        List<JSONObject> requiredFieldsJson = JSONArray.parseArray(basicCardRule.getRequiredFields(), JSONObject.class);
        List<StudentExtendDto> studentExtendDtos = new ArrayList<>();
        if (requiredFieldsJson.size() > 0) {
            for (JSONObject jsonObject : requiredFieldsJson) {
                StudentExtendDto studentExtendDto = new StudentExtendDto();
                String code = String.valueOf(jsonObject.get("code"));
                studentExtendDto.setFieldName(code);
                studentExtendDto.setValue("");
                studentExtendDtos.add(studentExtendDto);
            }
        }
        List<JSONObject> extendFieldsJson = JSONArray.parseArray(basicCardRule.getExtendFields(), JSONObject.class);
        if (extendFieldsJson.size() > 0) {
            for (JSONObject jsonObject : extendFieldsJson) {
                StudentExtendDto studentExtendDto = new StudentExtendDto();
                String code = String.valueOf(jsonObject.get("code"));
                studentExtendDto.setFieldName(code);
                studentExtendDto.setValue("");
                studentExtendDtos.add(studentExtendDto);
            }
        }
        return studentExtendDtos;
    }

    /**
     * 通用题卡html
     *
     * @param packageCode
     * @param cardContent
     * @param paperType
     * @param userId
     * @param cardPdfList
     * @param basicCardRule
     * @return
     * @throws IOException
     */
    public BasicAttachment cardHtml(String packageCode, String cardContent, String paperType, Long userId, List<PdfDto> cardPdfList, List<File> fileTempList, BasicCardRule basicCardRule) throws
            IOException {
        //通用题卡
        String cardTemp = cardContent;
        cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", paperType);
        //随机生成试卷条码并将图片转成base64
        if (Objects.nonNull(paperType)) {
            cardTemp = cardTemp.replaceAll("\\$\\{paperType\\}", GoogleBarCodeUtil.createBarCode(SystemConstant.convertPaperType(paperType), false));
        }
        if (Objects.nonNull(basicCardRule) && Objects.nonNull(basicCardRule.getExtendFields())) {
            JSONArray jsonObjectExtend = (JSONArray) JSONArray.parse(basicCardRule.getExtendFields());//扩展字段
            if (Objects.nonNull(jsonObjectExtend)) {
                int i = 0;
                while (i < jsonObjectExtend.size()) {
                    JSONObject object = (JSONObject) jsonObjectExtend.get(i);
                    cardTemp = cardTemp.replaceAll("\\$\\{" + object.get("code") + "\\}", "");
                    i++;
                }
            }
        }
        cardTemp = cardTemp.replaceAll("\\$\\{examDate\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{examTime\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{ticketNumber\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{siteNumber\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{studentCode\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{studentName\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{courseName\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{courseCode\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{examPlace\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{examRoom\\}", "");
        cardTemp = cardTemp.replaceAll("\\$\\{paperNumber\\}", "");

        //通用题卡生成卷袋贴条码
        String packageCodeImg = GoogleBarCodeUtil.createBarCode(packageCode, false);
        cardTemp = cardTemp.replaceAll("\\$\\{packageCodeDom\\}", "<img src='" + "data:image/png;base64," + packageCodeImg + "'><p>" + packageCode + "</p>");

        return printCommonService.saveAttachmentPdfFromHtml(packageCode + paperType, cardTemp, userId, cardPdfList, fileTempList);
    }

    /**
     * 通用题卡html
     *
     * @param htmlContent       html内容
     * @param paperType         卷型
     * @param basicCardRule     题卡规则
     * @param backupPackageCode 备用题卡条码号
     */
    public String replaceBackupCardHtmlParam(String htmlContent, String paperType, BasicCardRule basicCardRule, String backupPackageCode) {
        // 替换条码参数
        htmlContent = htmlContent.replaceAll("<img src=\"data:image/png;base64,\\$\\{examNumber\\}\">", "");
        htmlContent = htmlContent.replaceAll("\\$\\{examNumberStr\\}", "");

        //替换卷型参数
        htmlContent = htmlContent.replaceAll("\\$\\{paperTypeName\\}", StringUtils.isBlank(paperType) ? "" : paperType);
        //替换卷型条码（base64）
        if (Objects.nonNull(paperType)) {
            htmlContent = htmlContent.replaceAll("\\$\\{paperType\\}", GoogleBarCodeUtil.createBarCode(SystemConstant.convertPaperType(paperType), false));
        }
        // 替换考生变量参数
        if (Objects.nonNull(basicCardRule) && Objects.nonNull(basicCardRule.getExtendFields())) {
            JSONArray jsonObjectRequired = (JSONArray) JSONArray.parse(basicCardRule.getRequiredFields());//必选字段
            if (Objects.nonNull(jsonObjectRequired)) {
                int i = 0;
                while (i < jsonObjectRequired.size()) {
                    JSONObject object = (JSONObject) jsonObjectRequired.get(i);
                    htmlContent = htmlContent.replaceAll("\\$\\{" + object.get("code") + "\\}", "");
                    i++;
                }
            }

            JSONArray jsonObjectExtend = (JSONArray) JSONArray.parse(basicCardRule.getExtendFields());//扩展字段
            if (Objects.nonNull(jsonObjectExtend)) {
                int i = 0;
                while (i < jsonObjectExtend.size()) {
                    JSONObject object = (JSONObject) jsonObjectExtend.get(i);
                    htmlContent = htmlContent.replaceAll("\\$\\{" + object.get("code") + "\\}", "");
                    i++;
                }
            }
        }

        if (StringUtils.isNotBlank(backupPackageCode)) {
            //通用题卡生成卷袋贴条码
            String packageCodeImg = GoogleBarCodeUtil.createBarCode(backupPackageCode, false);
            htmlContent = htmlContent.replaceAll("\\$\\{packageCodeDom\\}", "<img src='" + "data:image/png;base64," + packageCodeImg + "'><p>" + backupPackageCode + "</p>");
        } else {
            htmlContent = htmlContent.replaceAll("\\$\\{packageCodeDom\\}", "");
        }
        return htmlContent;
    }

    public String getPaperType(Long printPlanId, Long examId, String paperNumber) {
        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(printPlanId);
        //抽取卷型
        DrawRuleEnum drawRule = Objects.nonNull(examPrintPlan.getDrawRule()) ? examPrintPlan.getDrawRule() : DrawRuleEnum.ONE;
        ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamIdAndCourseCodeAndPaperNumber(examId, null, paperNumber);
        // 单次抽取套数
        int drawCount = examTaskDetail.getDrawCount().intValue();

        String paperType = null;
        try {
            //未曝光卷型
            String unexposedPaperType = examTaskDetail.getUnexposedPaperType();
            //已曝光卷型
            String exposedPaperType = examTaskDetail.getExposedPaperType();
            String totalPaperType = examTaskDetail.getPaperType();
            String[] paperTypes;
            if (drawRule == DrawRuleEnum.ONE) {
                if (StringUtils.isBlank(unexposedPaperType)) {
                    throw ExceptionResultEnum.PAPER_ERROR.exception();
                }
                paperTypes = unexposedPaperType.split(",");
                if (paperTypes.length - drawCount < 0) {
                    throw ExceptionResultEnum.ERROR.exception("可用卷型数量小于抽取数量");
                }
            } else {
                if (StringUtils.isAllBlank(totalPaperType, unexposedPaperType)) {
                    throw ExceptionResultEnum.PAPER_ERROR.exception();
                }
                if (StringUtils.isNotBlank(unexposedPaperType)) {
                    paperTypes = unexposedPaperType.split(",");
                    // 未曝光卷型小于抽取数量，则使用所有卷型
                    if (paperTypes.length - drawCount < 0) {
                        paperTypes = totalPaperType.split(",");
                    }
                } else {
                    paperTypes = totalPaperType.split(",");
                }
            }
            paperType = randomPaperType(paperTypes, drawCount);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
        return paperType;
    }

}
