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

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.qmth.boot.tools.models.ByteArray;
import com.qmth.distributed.print.business.bean.dto.*;
import com.qmth.distributed.print.business.cache.CreatePdfCacheUtil;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
import com.qmth.distributed.print.business.enums.StudentClazzEnum;
import com.qmth.distributed.print.business.service.*;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.BasicAttachmentService;
import com.qmth.teachcloud.common.service.BasicClazzService;
import com.qmth.teachcloud.common.service.BasicSemesterService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.ConvertUtil;
import com.qmth.teachcloud.common.util.FileStoreUtil;
import com.qmth.teachcloud.common.util.RedisUtil;
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 org.springframework.util.CollectionUtils;

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

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

    @Resource
    BasicAttachmentService basicAttachmentService;

//    @Resource
//    FreemarkerUtil freemarkerUtil;

    @Resource
    @Lazy
    PrintCommonService printCommonService;

    @Resource
    ExamDetailService detailService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    FileStoreUtil fileStoreUtil;

    @Resource
    BasicClazzService basicClazzService;

    @Resource
    ExamDetailService examDetailService;

    @Resource
    ExamStudentService examStudentService;

    @Resource
    BasicTemplateService basicTemplateService;

    @Resource
    BasicSemesterService basicSemesterService;

    @Resource
    ExamTaskService examTaskService;

    @Resource
    ExamTaskDetailService examTaskDetailService;

    @Resource
    DictionaryConfig dictionaryConfig;

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

        String type = basicAttachment.getType();
        JSONObject jsonObject = JSONObject.parseObject(basicAttachment.getPath());

        if (Objects.nonNull(type) && Objects.equals(type, SystemConstant.PDF_PREFIX)) {
            String filePath = (String) jsonObject.get(SystemConstant.PATH);
            UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));

            JSONObject attachmentPath = JSONObject.parseObject(examDetail.getAttachmentPath());
            attachmentPath = Objects.isNull(attachmentPath) ? new JSONObject() : attachmentPath;
            JSONArray jsonArray = (JSONArray) attachmentPath.get(SystemConstant.PATH);
            jsonArray = Objects.isNull(jsonArray) ? new JSONArray() : jsonArray;

            JSONObject object = new JSONObject();
            object.put("printType", ClassifyEnum.CHECK_IN.name());
            File localFile;
            if (SystemConstant.LOCAL.equals(jsonObject.get(SystemConstant.TYPE))) {
                localFile = new File(filePath);
                object.put(SystemConstant.PDF_PATH, localFile.getPath());
                object.put(SystemConstant.TYPE, SystemConstant.LOCAL);
            } else {
                localFile = fileStoreUtil.ossDownload(filePath, filePath, uploadFileEnum.getFssType());
                object.put(SystemConstant.PDF_PATH, localFile.getPath());
                object.put(SystemConstant.TYPE, SystemConstant.OSS);
            }
            object.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.PDF);
            PdfDto pdfDto = PdfUtil.addPdfPage(localFile);

            byte[] data = ByteArray.fromFile(localFile).value();
            String md5 = ByteArray.md5(data).toHexString();
            object.put("pdfMd5", md5);

            jsonArray.add(object);
            attachmentPath.put(SystemConstant.PATH, jsonArray);
            examDetail.setAttachmentPath(attachmentPath.toJSONString());

            for (int i = 0; i < printCount; i++) {
                ordinaryPdfList.add(new PdfDto(localFile.getPath(), PageSizeEnum.A4, pdfDto.getPageCount()));
            }
        } else {
            printCommonService.saveAttachmentPdf(ClassifyEnum.CHECK_IN, examDetail, basicAttachment, ordinaryPdfList, printCount, 0, fileTempList);
        }
    }

//    /**
//     * 生成卷袋贴
//     *
//     * @param tag
//     * @param basicAttachment
//     * @param schoolName
//     * @param examStudentList
//     * @param variablePdfList
//     * @param printCount
//     * @param examDetailCourseList
//     * @throws IOException
//     */
//    public void createPaperPackage(boolean tag, BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer printCount, List<ExamDetailCourse> examDetailCourseList) throws IOException {
//        if (Objects.isNull(basicAttachment)) {
//            throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
//        }
//        Map<String, Object> htmlMap = new HashMap<>();
//        if (Objects.nonNull(examDetailCourseList) && examDetailCourseList.size() > 0) {
//            List<String> paperNumbers = examDetailCourseList.stream().map(s -> s.getPaperNumber()).collect(Collectors.toList());
//            List<String> courseCodes = examDetailCourseList.stream().map(s -> s.getCourseCode()).collect(Collectors.toList());
//            List<String> courseNames = examDetailCourseList.stream().map(s -> s.getCourseName()).collect(Collectors.toList());
//            htmlMap.put("courseName", String.join(", ", courseNames));
//            htmlMap.put("courseCode", String.join(", ", paperNumbers));
//            // 学院
////            Set<String> stringSet = new HashSet<>();
////            List<BasicCourse> basicCourses = basicCourseService.findBySchoolIdAndCourseCode(examDetail.getSchoolId(), courseCodes);
////            for (BasicCourse basicCours : basicCourses) {
////                List<SysOrg> sysOrgs = sysOrgService.findParentsByOrgId(basicCours.getTeachingRoomId());
////                Set<String> collegeName = sysOrgs.stream().filter(m -> OrgTypeEnum.COLLEGE.equals(m.getType())).map(m -> m.getName()).collect(Collectors.toSet());
////                if (CollectionUtils.isEmpty(collegeName)) {
////                    collegeName = sysOrgs.stream().filter(m -> OrgTypeEnum.FACULTY.equals(m.getType())).map(m -> m.getName()).collect(Collectors.toSet());
////                }
////                if (!CollectionUtils.isEmpty(collegeName)) {
////                    stringSet.addAll(collegeName);
////                }
////            }
////            htmlMap.put("collegeName", CollectionUtils.isEmpty(stringSet) ? "" : String.join(",", stringSet));
//        } else {
//            htmlMap.put("courseName", "");
//            htmlMap.put("courseCode", "");
//            htmlMap.put("collegeName", "");
//        }
//        Set<Long> clazzIdSet = new HashSet<>();
//        for (ExamDetailCourse examDetailCourse : examDetailCourseList) {
//            String clazzInfo = examDetailCourse.getClazzId();
//            if (SystemConstant.strNotNull(clazzInfo)) {
//                Set<Long> clazzIdSetCell = Arrays.stream(clazzInfo.split(",")).map(SystemConstant::convertIdToLong).collect(Collectors.toSet());
//                clazzIdSet.addAll(clazzIdSetCell);
//            }
//        }
//        List<Long> classIds = new ArrayList<>(clazzIdSet);
//
////        String campusName = CollectionUtils.isEmpty(classIds) ? "" : basicCampusService.findCampusNamesByClazzIdList(classIds, ",");
//        htmlMap.put("schoolName", schoolName);
////        htmlMap.put("campusName", campusName);
//        htmlMap.put("examSite", examDetail.getExamPlace());
//        htmlMap.put("examRoom", examDetail.getExamRoom());
//        htmlMap.put("startTime", DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DEFAULT_DATE_PATTERN));
//        htmlMap.put("endTime", DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DEFAULT_DATE_PATTERN));
//        htmlMap.put("paperCode", examDetail.getPackageCode());
//        htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
//
//        List<String> extendColumnList = examStudentList.stream().map(m -> m.getExtendFields()).distinct().collect(Collectors.toList());
//        Set<String> startCollege = new HashSet();
//        Set<String> className = new HashSet();
//        Set<String> proctorCollege = new HashSet();
//        Set<String> examManager = new HashSet();
//
//        String className1 = examDetailService.findClazzNamesByClazzIds(classIds, ",");
//
//        if (Objects.nonNull(extendColumnList) && extendColumnList.size() > 0) {
//            for (String s : extendColumnList) {
//                List<Map> mapList = JSONObject.parseArray(s, Map.class);
//                for (Map map : mapList) {
//                    if (Objects.equals("startCollege", map.get("code").toString())) {
//                        startCollege.add(map.get("value").toString());
//                    }
//                    if (Objects.equals("className", map.get("code").toString())) {
//                        className.add(map.get("value").toString());
//                    }
//                    if (Objects.equals("proctorCollege", map.get("code").toString())) {
//                        proctorCollege.add(map.get("value").toString());
//                    }
//                    if (Objects.equals("examManager", map.get("code").toString())) {
//                        examManager.add(map.get("value").toString());
//                    }
//                }
//            }
//        }
//
//        htmlMap.put("startCollege", String.join(",", startCollege));
//        htmlMap.put("className", StringUtils.isNotBlank(className1) ? className1 : String.join(",", className));
//        htmlMap.put("proctorCollege", String.join(",", proctorCollege));
//        htmlMap.put("examManager", String.join(",", examManager));
//
////        List<ExamStudent> tempList = examStudentList.stream().filter(s -> (Objects.nonNull(s.getSiteNumber()) && !Objects.equals("", s.getSiteNumber().trim()))).collect(Collectors.toList());
////        String minSite = "", maxSite = "";
////        if (Objects.nonNull(tempList) && tempList.size() > 0) {
////            minSite = tempList.stream().min((a, b) -> a.getSiteNumber().compareTo(b.getSiteNumber())).get().getSiteNumber();
////            maxSite = tempList.stream().max((a, b) -> a.getSiteNumber().compareTo(b.getSiteNumber())).get().getSiteNumber();
////        }
//
//        Optional<ExamStudentCourseDto> minSite = null;
//        Optional<ExamStudentCourseDto> maxSite = null;
//        List<ExamStudentCourseDto> tempList = examStudentList.stream().filter(s -> (Objects.nonNull(s.getSiteNumber()) && !Objects.equals("", s.getSiteNumber().trim()))).collect(Collectors.toList());
//        if (Objects.nonNull(tempList) && tempList.size() > 0) {
////            for (ExamStudentCourseDto e : tempList) {
////                char[] chars = e.getSiteNumber().toLowerCase().toCharArray();
////                String ascii = "";
////                for (int i = 0; i < chars.length; i++) {
////                    ascii = ascii + chars[i];
////                }
////                e.setAscii(ascii.hashCode());
////            }
//            minSite = tempList.stream().min(Comparator.comparing(s -> s.getSiteNumber().hashCode()));
//            maxSite = tempList.stream().max(Comparator.comparing(s -> s.getSiteNumber().hashCode()));
//        }
//
//        htmlMap.put("minSite", Optional.ofNullable(minSite).map(s -> s.get().getSiteNumber()).orElse(""));
//        htmlMap.put("maxSite", Optional.ofNullable(maxSite).map(s -> s.get().getSiteNumber()).orElse(""));
//        htmlMap.put("studentCount", examStudentList != null && examStudentList.size() > 0 ? examStudentList.size() : examDetail.getPrintCount());
//
//        String tagValue = tag ? "订" : null;
//        htmlMap.put("tag", tagValue);
//
//        htmlMap.computeIfAbsent("basicAttachment", v -> basicAttachment);
//        htmlMap.computeIfAbsent("variablePdfList", v -> variablePdfList);
//        htmlMap.computeIfAbsent("printCount", v -> printCount);
//        htmlMap.computeIfAbsent("sequence", v -> 1);
//        htmlMap.computeIfAbsent("examDetail", v -> examDetail);
//        htmlMap.computeIfAbsent("printType", v -> ClassifyEnum.PACKAGE);
//        freemarkerUtil.createPaperPackage(htmlMap);
//    }

    /**
     * 生成卷袋贴
     *
     * @param schoolName
     * @param examStudentList
     * @param variablePdfList
     * @param printCount
     * @param examDetailCourseList
     * @param fileTempList
     */
    public void createPaperPackage(Long templateId, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer backupCount, Integer printCount, List<ExamDetailCourse> examDetailCourseList, Long examId, List<File> fileTempList) {
        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.getByCourseCodeAndPaperNumber(examDetail.getSchoolId(), examId, detailCourse.getCourseCode(), detailCourse.getPaperNumber());
            ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamTaskId(examTask.getId());
            List<JSONObject> objectList = JSON.parseArray(examTaskDetail.getPaperAttachmentIds(), JSONObject.class);
            for (JSONObject jsonObject : objectList) {
                int pages = jsonObject.getIntValue("pages");
                isTag = pages > 2;
                pdfPackageDto.setTag(isTag);
                if (isTag) {
                    break;
                }
            }
        }

        // 标题信息
        List<JSONObject> objectTitleList = JSON.parseArray(object.getString("title"), JSONObject.class);
        List<Map<String, String>> titlePlate = new ArrayList<>();
        for (JSONObject jsonObject : objectTitleList) {
            Map<String, String> titleMap = new HashMap<>();
            if (jsonObject.getBoolean("enable")) {
                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);

        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) {
            if (jsonObject.getBoolean("enable")) {
                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().map(ExamStudent::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> 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", 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 -> m.getStudentClazzType().equals(StudentClazzEnum.BASIC_CLAZZ) && StringUtils.isNotBlank(m.getClazzName())).map(ExamStudent::getClazzName).collect(Collectors.toSet());
                    if (!clazzNames.isEmpty()) {
                        stringSet.addAll(clazzNames);
                    }
                    Set<String> teachClazzNames = examStudentList.stream().filter(m -> m.getStudentClazzType().equals(StudentClazzEnum.TEACH_CLAZZ) && StringUtils.isNotBlank(m.getTeachClazzName())).map(ExamStudent::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", String.join(SystemConstant.COMMA_OF_CHINESE, stringSet));
                    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 if ("paperCount".equals(code)) {
//                    Map<String, String> basicMap = new HashMap<>();
//                    basicMap.put("code", code);
//                    basicMap.put("name", name);
//                    basicMap.put("value", examStudentList.size() + " + " + printCount);
//                    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);
                }
            }
        }
        Map<String, String> basicMap1 = new HashMap<>();
        basicMap1.put("code", "paperCount");
        basicMap1.put("name", "试卷数量");
        basicMap1.put("value", examStudentList.size() + " + " + backupCount);
        basicPlate.add(basicMap1);

        Map<String, String> basicMap2 = new HashMap<>();
        basicMap2.put("code", "examCount");
        basicMap2.put("name", "应考人数");
        basicMap2.put("value", String.valueOf(examStudentList.size()));
        basicPlate.add(basicMap2);

        Map<String, String> basicMap3 = new HashMap<>();
        basicMap3.put("code", "actualExamCount");
        basicMap3.put("name", "实考人数");
        basicMap3.put("value", "");
        basicPlate.add(basicMap3);

        pdfPackageDto.setBasicPlate(basicPlate);
        printCommonService.saveAttachmentPackagePdf(pdfPackageDto, examDetail, variablePdfList, printCount, fileTempList);
    }

//    /**
//     * 创建签到表
//     *
//     * @param basicAttachment
//     * @param schoolName
//     * @param examDetail
//     * @param examStudentList
//     * @param variablePdfList
//     * @param printCount
//     * @param examDetailCourseList
//     */
//    public void createSignBook(BasicAttachment basicAttachment, String schoolName, ExamDetail
//            examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer
//                                       printCount, List<ExamDetailCourse> examDetailCourseList) throws IOException {
//        if (Objects.isNull(basicAttachment)) {
//            throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
//        }
//        Map<String, Object> htmlMap = new HashMap<>();
//        if (Objects.nonNull(examDetailCourseList) && examDetailCourseList.size() > 0) {
//            List<String> paperNumbers = examDetailCourseList.stream().map(ExamDetailCourse::getPaperNumber).collect(Collectors.toList());
//            List<String> courseNames = examDetailCourseList.stream().map(ExamDetailCourse::getCourseName).collect(Collectors.toList());
//            htmlMap.put("courseName", String.join(", ", courseNames));
//            htmlMap.put("courseCode", String.join(", ", paperNumbers));
//        } else {
//            htmlMap.put("courseName", "");
//            htmlMap.put("courseCode", "");
//        }
//        htmlMap.put("schoolName", schoolName);
//        htmlMap.put("examRoom", examDetail.getExamRoom());
//
//        List<String> extendColumnList = examStudentList.stream().map(ExamStudent::getExtendFields).distinct().collect(Collectors.toList());
//        Set<String> classTeacher = new HashSet();
//        if (extendColumnList.size() > 0) {
//            for (String s : extendColumnList) {
//                List<Map> mapList = JSONObject.parseArray(s, Map.class);
//                for (Map map : mapList) {
//                    if (Objects.equals("classTeacher", map.get("code").toString())) {
//                        classTeacher.add(map.get("value").toString());
//                    }
//                }
//            }
//        }
//        htmlMap.put("classTeacher", String.join(",", classTeacher));
//        htmlMap.put("startTime", DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DEFAULT_DATE_PATTERN));
//        htmlMap.put("endTime", DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DEFAULT_DATE_PATTERN));
//        htmlMap.put("paperCode", examDetail.getPackageCode());
//        htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
//
//        int pageSize = 60;
//        int halfPageSize = pageSize / 2;
//
//        if (examStudentList.size() > 0) {
//            int totalCount = examStudentList.size();
//            List<Map> subList = new ArrayList<>();
//            int pageCount = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
//            for (int i = 0; i < pageCount; i++) {
//                Map subMap = new HashMap();
//                subMap.put("index", i + 1);
//                int studentCount;
//                List<ExamStudentCourseDto> subStudents;
//                if (pageCount == 1) {
//                    studentCount = totalCount;
//                    subStudents = examStudentList;
//                } else if (i == pageCount - 1) {
//                    studentCount = totalCount - (pageCount - 1) * pageSize;
//                    subStudents = examStudentList.subList(pageSize * i, examStudentList.size());
//                } else {
//                    studentCount = pageSize;
//                    subStudents = examStudentList.subList(pageSize * i, pageSize * (i + 1));
//                }
//                subMap.put("studentCount", totalCount);
//                List<ExamStudentDto> examStudentList1 = new ArrayList<>();
//                List<ExamStudentDto> examStudentList2 = new ArrayList<>();
//
//                Gson gson = new Gson();
//                int mod = subStudents.size() % 2;
//                int htmlTableCount = mod == 0 ? subStudents.size() / 2 : subStudents.size() / 2 + 1;
//                for (int j = 0; j < htmlTableCount; j++) {
//                    ExamStudentDto examStudentDto = gson.fromJson(gson.toJson(subStudents.get(j)), ExamStudentDto.class);
//                    examStudentDto.setIndex(j + 1);
//                    String clazzName = getClassName(examStudentDto);
//                    examStudentDto.setClazzName(clazzName);
//                    examStudentList1.add(examStudentDto);
//                }
//                for (int j = htmlTableCount; j < subStudents.size(); j++) {
//                    ExamStudentDto examStudentDto = gson.fromJson(gson.toJson(subStudents.get(j)), ExamStudentDto.class);
//                    examStudentDto.setIndex(j + 1);
//                    String clazzName = getClassName(examStudentDto);
//                    examStudentDto.setClazzName(clazzName);
//                    examStudentList2.add(examStudentDto);
//                }
////                if (examStudentList1.size() > examStudentList2.size()) {
////                    for (int j = subStudents.size() - htmlTableCount; j < examStudentList1.size(); j++) {
////                        examStudentList2.add(new ExamStudentDto());
////                    }
////                }
//                if (examStudentList1.size() < halfPageSize) {
//                    int examStudentList1Size = examStudentList1.size();
//                    for (int j = 0; j < halfPageSize - examStudentList1Size; j++) {
//                        ExamStudentDto examStudentDto = new ExamStudentDto();
//                        examStudentDto.setIndex(null);
//                        examStudentDto.setSiteNumber("");
//                        examStudentDto.setStudentName("");
//                        examStudentDto.setClazzName("");
//                        examStudentList1.add(examStudentDto);
//                    }
//                }
//                if (examStudentList2.size() < halfPageSize) {
//                    int examStudentList2Size = examStudentList2.size();
//                    for (int j = 0; j < halfPageSize - examStudentList2Size; j++) {
//                        ExamStudentDto examStudentDto = new ExamStudentDto();
//                        examStudentDto.setIndex(null);
//                        examStudentDto.setSiteNumber("");
//                        examStudentDto.setStudentName("");
//                        examStudentDto.setClazzName("");
//                        examStudentList2.add(examStudentDto);
//                    }
//                }
//                subMap.put("studentList1", examStudentList1);
//                subMap.put("studentList2", examStudentList2);
//                subList.add(subMap);
//            }
//            htmlMap.put("subList", subList);
//        } else {
//            int totalCount = examDetail.getPrintCount();
//            List<Map> subList = new ArrayList<>();
//            int pageCount = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
//            for (int i = 0; i < pageCount; i++) {
//                Map subMap = new HashMap();
//                subMap.put("index", i + 1);
//                int studentCount;
//                if (pageCount == 1) {
//                    studentCount = pageSize;
//                } else if (i == pageCount - 1) {
//                    studentCount = totalCount - (pageCount - 1) * pageSize;
//                } else {
//                    studentCount = pageSize;
//                }
//                subMap.put("studentCount", totalCount);
//                List<ExamStudentDto> examStudentList1 = new ArrayList<>();
//                List<ExamStudentDto> examStudentList2 = new ArrayList<>();
//
//                int mod = studentCount % 2;
//                int htmlTableCount = mod == 0 ? studentCount / 2 : studentCount / 2 + 1;
//                for (int j = 0; j < htmlTableCount; j++) {
//                    ExamStudentDto examStudentDto = new ExamStudentDto();
//                    examStudentDto.setIndex(null);
//                    examStudentDto.setStudentName("");
//                    examStudentDto.setClazzName("");
//                    examStudentList1.add(examStudentDto);
//                }
//                for (int j = htmlTableCount; j < studentCount; j++) {
//                    ExamStudentDto examStudentDto = new ExamStudentDto();
//                    examStudentDto.setIndex(null);
//                    examStudentDto.setStudentName("");
//                    examStudentDto.setClazzName("");
//                    examStudentList2.add(examStudentDto);
//                }
//                if (examStudentList1.size() < halfPageSize) {
//                    for (int j = 0; j < halfPageSize - examStudentList1.size(); j++) {
//                        ExamStudentDto examStudentDto = new ExamStudentDto();
//                        examStudentDto.setIndex(null);
//                        examStudentDto.setSiteNumber("");
//                        examStudentDto.setStudentName("");
//                        examStudentDto.setClazzName("");
//                        examStudentList1.add(examStudentDto);
//                    }
//                }
//                if (examStudentList2.size() < halfPageSize) {
//                    for (int j = 0; j < halfPageSize - examStudentList2.size(); j++) {
//                        ExamStudentDto examStudentDto = new ExamStudentDto();
//                        examStudentDto.setIndex(null);
//                        examStudentDto.setSiteNumber("");
//                        examStudentDto.setStudentName("");
//                        examStudentDto.setClazzName("");
//                        examStudentList2.add(examStudentDto);
//                    }
//                }
//                subMap.put("studentList1", examStudentList1);
//                subMap.put("studentList2", examStudentList2);
//                subList.add(subMap);
//            }
//            htmlMap.put("subList", subList);
//        }
//        htmlMap.computeIfAbsent("basicAttachment", v -> basicAttachment);
//        htmlMap.computeIfAbsent("variablePdfList", v -> variablePdfList);
//        htmlMap.computeIfAbsent("printCount", v -> printCount);
//        htmlMap.computeIfAbsent("sequence", v -> 2);
//        htmlMap.computeIfAbsent("examDetail", v -> examDetail);
//        htmlMap.computeIfAbsent("printType", v -> ClassifyEnum.SIGN);
//        freemarkerUtil.createSignBook(htmlMap);
//    }

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

        JSONObject jsonObject = JSON.parseObject(basicTemplate.getDisplayRange());
        List<JSONObject> objectList = JSON.parseArray(jsonObject.getString("basic"), JSONObject.class);

        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) {
            if (!object.getBoolean("enable")) {
                continue;
            }
            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().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().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 ("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);
        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
        for (JSONObject object : tableList) {
            if (object.getBoolean("enable")) {
                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("clazzName")) {
                studentMap.put("clazzName", StringUtils.isBlank(examStudentCourseDto.getTeachClazzName()) ? examStudentCourseDto.getClazzName() : examStudentCourseDto.getTeachClazzName());
            }
            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, variablePdfList, printCount, fileTempList);
    }

    /**
     * 替换html通用模版中的条码信息
     *
     * @param content 题卡详细内容
     */
    public String resetHtmlTemplateBar(String content) {
        content = content.replaceAll("<img src=\"data:image/png;base64,\\$\\{examNumber\\}\">", "");
        content = content.replaceAll("\\$\\{examNumberStr\\}", "");
        return content;
    }

    /**
     * 替换自定义题卡参数
     *
     * @param examCardDetail
     * @return
     * @throws IOException
     */
    public String replaceHtmlCard(ExamCardDetail examCardDetail, BasicCardRule basicCardRule) throws IOException {
        //通用题卡
        String cardTemp = examCardDetail.getHtmlContent();
        cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", "");
        //随机生成试卷条码并将图片转成base64
        cardTemp = cardTemp.replaceAll("\\$\\{paperType\\}", "");
        cardTemp = cardTemp.replaceAll("<img src=\"data:image/png;base64,\\$\\{examNumber\\}\">", "");
        cardTemp = cardTemp.replaceAll("\\$\\{examNumberStr\\}", "");
        if (Objects.nonNull(basicCardRule) && Objects.nonNull(basicCardRule.getExtendFields())) {
            JSONArray jsonObjectExtend = (JSONArray) JSONArray.parse(basicCardRule.getExtendFields());//扩展字段
            if (Objects.nonNull(jsonObjectExtend)) {
                for (int i = 0; i < jsonObjectExtend.size(); i++) {
                    JSONObject object = (JSONObject) jsonObjectExtend.get(i);
                    cardTemp = cardTemp.replaceAll("\\$\\{" + object.get("code") + "\\}", "");
                }
            }
        }
        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\\}", "");

        // 根据题卡规则必选字段，替换相应值，没有则“”
        List<StudentExtendDto> studentExtendDtos = createExtendObjectNull(basicCardRule);
        if (studentExtendDtos != null) {
            for (StudentExtendDto extendDto : studentExtendDtos) {
                cardTemp = cardTemp.replaceAll("\\$\\{" + extendDto.getFieldName() + "\\}", String.valueOf(extendDto.getValue()));
            }
        }

        return cardTemp;
    }

    /**
     * 获取题卡attachmentId
     *
     * @param examCardDetail
     * @param attachmentIds
     */
    public void getCardAttachmentId(ExamCardDetail examCardDetail, Set<Long> attachmentIds) {
        if (Objects.nonNull(examCardDetail.getAttachmentId()) && !Objects.equals("", examCardDetail.getAttachmentId())) {
            JSONObject jsonObjectCard = JSONObject.parseObject(examCardDetail.getAttachmentId());
            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 pdfList        考生试卷集合
     * @param waterMarkNames 水印内容
     */
    public PdfDto getExamStudentPaperPdf(String stuPaperType, List<PaperPdfDto> paperPdfDto, List<PdfDto> pdfList, 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();
                    pdfList.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 pdfList     备份试卷集合
     */
    public PdfDto getPaperPdf(List<PaperPdfDto> paperPdfDto, Integer backupCount, List<PdfDto> pdfList) throws
            IOException {
        Set<Integer> pagesList = new HashSet<>();
        boolean tag = false;
        if (!CollectionUtils.isEmpty(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++) {
                    pdfList.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 examTaskDetail 命题任务上传试卷信息
     * @param fileTempList
     */
    public List<PaperPdfDto> getPaperPdfFile(String paperType, ExamTaskDetail examTaskDetail, List<File> fileTempList) throws Exception {
        String[] paperTypes = paperType.split(",");
        List<PaperPdfDto> paperPdfDtoList = new ArrayList<>();
        PaperPdfDto paperPdfDto = null;
        JSONArray jsonArrayPaper = JSONArray.parseArray(examTaskDetail.getPaperAttachmentIds());
        for (int i = 0; i < jsonArrayPaper.size(); i++) {
            JSONObject object = jsonArrayPaper.getJSONObject(i);
            if (Objects.nonNull(object.get("attachmentId")) && !Objects.equals("", object.get("attachmentId"))) {
                Long attachmentId = Long.parseLong((String) (object.get("attachmentId")));
                BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
                Optional.ofNullable(basicAttachment).orElseThrow(() -> ExceptionResultEnum.ATTACHMENT_IS_NULL.exception("所在路径不存在"));

                String name = (String) object.get("name");
                JSONObject jsonObject = (JSONObject) object.get("original");
                // 返回抽中的试卷
                for (String type : paperTypes) {
                    if (Objects.equals(name.toUpperCase(), type.toUpperCase())) {
                        File file = teachcloudCommonService.getFile(basicAttachment.getPath(), false, fileTempList);
                        int pages = (int) object.get("pages");

                        PageSizeEnum pageSizeEnum = PageSizeEnum.valueOf((String) jsonObject.get("pageSize"));
                        Optional.ofNullable(pageSizeEnum).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未设置pdf格式"));

                        paperPdfDto = new PaperPdfDto(type, file, pages, pageSizeEnum);
                        paperPdfDtoList.add(paperPdfDto);
                        break;
                    }
                }

            }
        }
        return paperPdfDtoList;
    }

    /**
     * 抽取试卷
     *
     * @param drawRule
     * @param examTaskDetail
     * @param key
     * @return
     */
    public String getPaperType(DrawRuleEnum drawRule, ExamTaskDetail examTaskDetail, String key) {
        //抽取卷型
        drawRule = Objects.nonNull(drawRule) ? drawRule : DrawRuleEnum.ONE;
        //未曝光卷型
        String unexposedPaperType = examTaskDetail.getUnexposedPaperType();
        //已曝光卷型
        String exposedPaperType = examTaskDetail.getExposedPaperType();

        if (drawRule == DrawRuleEnum.ONE) {
            if (Objects.isNull(unexposedPaperType) || Objects.equals(unexposedPaperType.trim(), "")) {
//                CreatePdfCacheUtil.deletePaperType(key);
                throw ExceptionResultEnum.PAPER_ERROR.exception();
            }
        } else {
            if ((Objects.isNull(exposedPaperType) || Objects.equals(exposedPaperType.trim(), "")) && (Objects.isNull(unexposedPaperType) || Objects.equals(unexposedPaperType.trim(), ""))) {
//                CreatePdfCacheUtil.deletePaperType(key);
                throw ExceptionResultEnum.PAPER_ERROR.exception();
            }
        }
        // 单次抽取套数
        int drawCount = examTaskDetail.getDrawCount().intValue();
        String paperType = null;
        String[] paperTypes;
        boolean lock = true;
        for (int i = 0; i < SystemConstant.MAX_RETRY_COUNT; i++) {
            lock = redisUtil.lock(key, SystemConstant.REDIS_CACHE_TIME_OUT);
            if (lock) {
                try {
                    paperType = CreatePdfCacheUtil.getPaperType(key);
                    if (StringUtils.isBlank(paperType)) {
                        if (drawRule == DrawRuleEnum.ONE) {
                            paperTypes = unexposedPaperType.split(",");
                            if (paperTypes.length - drawCount < 0) {
                                throw ExceptionResultEnum.ERROR.exception("没有可用卷型");
                            }
                        } else {
                            if (Objects.nonNull(unexposedPaperType)) {
                                paperTypes = unexposedPaperType.split(",");
                            } else {
                                paperTypes = exposedPaperType.split(",");
                            }
                        }
                        paperType = randomPaperType(paperTypes, exposedPaperType, drawCount);
                        CreatePdfCacheUtil.setPaperType(key, paperType);
                    }
                    break;
                } catch (Exception e) {
                    log.error(SystemConstant.LOG_ERROR, e);
                } finally {
                    redisUtil.releaseLock(key);
                }
            } else {//未获取到锁，等待500毫秒继续获取
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    log.error(SystemConstant.LOG_ERROR, e);
                }
            }
        }
        log.info("getPaperType key:{},paperType:{},lock:{}", key, paperType, lock);
        if (!lock) {
            log.info("getPaperType 未获取到锁,key:{}", key);
            throw ExceptionResultEnum.PAPER_TYPE_ERROR.exception();
        }
        return paperType;
    }

    private String randomPaperType(String[] unexposedPaperTypes, String exposedPaperTypes, int drawCount) {
        List<String> finalTypes = new ArrayList<>();
        List<String> unexposedPaperTypesList = new ArrayList<>(Arrays.asList(unexposedPaperTypes));
        List<String> exposedPaperTypesList = StringUtils.isBlank(exposedPaperTypes) ? new ArrayList<>() : new ArrayList<>(Arrays.asList(exposedPaperTypes.split(",")));
        if (unexposedPaperTypesList.size() - drawCount >= 0) {
            for (int i = 0; i < drawCount; i++) {
                int paperRandom = new Random().nextInt(unexposedPaperTypesList.size());
                finalTypes.add(unexposedPaperTypesList.get(paperRandom));
                unexposedPaperTypesList.remove(paperRandom);
            }

        } else {
            for (int i = 0; i < unexposedPaperTypesList.size(); i++) {
                int paperRandom = new Random().nextInt(unexposedPaperTypesList.size());
                finalTypes.add(unexposedPaperTypesList.get(paperRandom));
                unexposedPaperTypesList.remove(paperRandom);
            }
            for (int i = 0; i < drawCount - unexposedPaperTypesList.size(); i++) {
                int paperRandom = new Random().nextInt(exposedPaperTypesList.size());
                finalTypes.add(exposedPaperTypesList.get(paperRandom));
                exposedPaperTypesList.remove(paperRandom);
            }
        }
        finalTypes = finalTypes.stream().sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
        return String.join(",", finalTypes);
    }

    /**
     * 合并A3 pdf
     *
     * @param fileTempList
     * @param list
     * @return
     * @throws IOException
     */
    public String mergeA3Pdf(List<File> fileTempList, List<PdfDto>... list) throws IOException {
        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, fileTempList);
    }

    /**
     * 合并A4 pdf
     *
     * @param list
     * @return
     * @throws IOException
     */
    public String mergeA4Pdf(List<File> fileTempList, List<PdfDto>... list) throws IOException {
        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 tbTask
     * @param userId
     * @param examDetail
     * @param basicPrintConfig
     * @param fileTempList
     * @return
     * @throws IOException
     */
    @Transactional
    public BasicAttachment mergePdfSaveDb(String dirNamePaper,
                                          String dirNameCardA3,
                                          TBTask tbTask,
                                          Long userId,
                                          ExamDetail examDetail,
                                          BasicPrintConfig basicPrintConfig,
                                          List<File> fileTempList) throws Exception {
        File localA4PdfFile = null, localPaperPdfFile = null, localA3PdfCardFile = null;
        BasicAttachment basicAttachment = null;
        // 试卷+题卡
        if (StringUtils.isNotBlank(dirNamePaper)) {
            dirNamePaper = dirNamePaper.replaceAll("\\\\", SystemConstant.ORG_SPLIT);
            localPaperPdfFile = new File(dirNamePaper);
            basicAttachment = basicAttachmentService.saveAttachmentPdf(dirNamePaper, userId);
            if (StringUtils.isBlank(tbTask.getImportFileName())) {
                tbTask.setImportFileName(basicAttachment.getName());
            }
            if (StringUtils.isBlank(tbTask.getImportFilePath())) {
                tbTask.setImportFilePath(basicAttachment.getPath());
            }
            examDetail.setAttachmentId(basicAttachment.getId());
        }
        // 题卡
        if (StringUtils.isNotBlank(dirNameCardA3)) {
            dirNameCardA3 = dirNameCardA3.replaceAll("\\\\", SystemConstant.ORG_SPLIT);
            localA3PdfCardFile = new File(dirNameCardA3);
            basicAttachment = basicAttachmentService.saveAttachmentPdf(dirNameCardA3, userId);
            if (StringUtils.isBlank(tbTask.getImportFileName())) {
                tbTask.setImportFileName(basicAttachment.getName());
            }
            if (StringUtils.isBlank(tbTask.getImportFilePath())) {
                tbTask.setImportFilePath(basicAttachment.getPath());
            }
            examDetail.setCardAttachmentId(basicAttachment.getId());
        }
        examDetail.setPaperPages(PdfUtil.getPdfPages(localPaperPdfFile));
        examDetail.setCardPages(PdfUtil.getPdfPages(localA3PdfCardFile));
        examDetail.setPagesA4(PdfUtil.getPdfPages(localA4PdfFile));
        if (PrintMethodEnum.AUTO == basicPrintConfig.getPrintMethod()) {
            examDetail.setStatus(ExamDetailStatusEnum.WAITING);
        } else {
            examDetail.setStatus(ExamDetailStatusEnum.READY);
        }
        detailService.saveOrUpdate(examDetail);
        return basicAttachment;
    }

    /**
     * 考生题卡html
     *
     * @param studentContent     题卡html内容
     * @param examStudent        考生对象
     * @param examDetail         考场对象
     * @param examDetailCourse   考场课程对象
     * @param userId             当前用户ID
     * @param examStudentPdfList 考生题卡集合
     * @param basicCardRule      题卡规则
     */
    public BasicAttachment examStudentHtml(String studentContent, ExamStudent examStudent, String
            paperType, ExamDetail examDetail, ExamDetailCourse examDetailCourse,
                                           Long userId, List<PdfDto> examStudentPdfList, BasicCardRule basicCardRule,
                                           List<File> fileTempList) throws IOException {
        String studentHtml = studentContent;
        // 生成学生考号条码并将图片转成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.getTicketNumber() != null ? GoogleBarCodeUtil.createBarCode(examStudent.getTicketNumber(), false) : "");
        studentHtml = studentHtml.replaceAll("\\$\\{examNumberStr\\}", examStudent != null && examStudent.getTicketNumber() != null ? examStudent.getTicketNumber() : "");
        // 随机生成学生试卷条码并将图片转成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 : "");

        // 根据题卡规则必选字段，替换相应值，没有则“”
        List<StudentExtendDto> studentExtendDtos = createExtendObject(examDetail, examStudent, basicCardRule);
        if (studentExtendDtos != null) {
            for (StudentExtendDto extendDto : studentExtendDtos) {
                studentHtml = studentHtml.replaceAll("\\$\\{" + extendDto.getFieldName() + "\\}", String.valueOf(extendDto.getValue()));
            }
        }

        //学生题卡
        BasicAttachment examStudentAttachment = printCommonService.saveAttachmentHtml(examDetail.getSchoolId() + "|" + examDetailCourse.getCourseCode() + (examStudent != null && examStudent.getTicketNumber() != null ? "|" + examStudent.getTicketNumber() : ""), 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 sequence         序号
     * @param cardContent      题卡内容
     * @param examDetail       考场对象
     * @param examDetailCourse 考场课程对象
     * @param jsonArray        组装json返回
     * @param userId           当前用户ID
     * @param cardPdfList      备用题卡集合
     * @param basicCardRule    题卡规则对象
     * @param fileTempList
     */
    public BasicAttachment cardHtml(String sequence, String cardContent, ExamDetail examDetail, ExamDetailCourse examDetailCourse, String paperType, JSONArray jsonArray, Long userId, List<PdfDto> cardPdfList, BasicCardRule basicCardRule, List<File> fileTempList) 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 packageCode = examDetail.getPackageCode() + sequence;
        String packageCodeImg = GoogleBarCodeUtil.createBarCode(packageCode, false);
        // 上传通卡
        if (cardTemp.contains("<div class=\"page-box page-box-0\">")) {
            String packageCodeDiv = "<div class=\"page-box page-box-0\"><div class=\"package-number\" style=\"position: absolute;width: 200px;height: 40px;top: 10px;right: 25%;margin-left: -100px;text-align: center;z-index: 99;\"><img src=\"data:image/png;base64," + packageCodeImg + "\" style=\"display: block; height: 28px; width: 100%\" /><p style=\"line-height: 1; font-size: 12px; margin: 0;\">" + packageCode + "</p></div>";
            cardTemp = cardTemp.replaceAll("<div class=\"page-box page-box-0\">", packageCodeDiv);
        } else if (cardTemp.contains("<div class=\"page-box page-box-A3 page-box-0\">")) {
            String packageCodeDiv = "<div class=\"page-box page-box-A3 page-box-0\"><div class=\"package-number\" style=\"position: absolute;width: 200px;height: 40px;top: 10px;right: 25%;margin-left: -100px;text-align: center;z-index: 99;\"><img src=\"data:image/png;base64," + packageCodeImg + "\" style=\"display: block; height: 28px; width: 100%\" /><p style=\"line-height: 1; font-size: 12px; margin: 0;\">" + packageCode + "</p></div>";
            cardTemp = cardTemp.replaceAll("<div class=\"page-box page-box-A3 page-box-0\">", packageCodeDiv);
        } else if (cardTemp.contains("<div class=\"page-box page-box-A3 page-box-0 page-box-less\">")) {
            String packageCodeDiv = "<div class=\"page-box page-box-A3 page-box-0 page-box-less\"><div class=\"package-number\" style=\"position: absolute;width: 200px;height: 40px;top: 10px;right: 25%;margin-left: -100px;text-align: center;z-index: 99;\"><img src=\"data:image/png;base64," + packageCodeImg + "\" style=\"display: block; height: 28px; width: 100%\" /><p style=\"line-height: 1; font-size: 12px; margin: 0;\">" + packageCode + "</p></div>";
            cardTemp = cardTemp.replaceAll("<div class=\"page-box page-box-A3 page-box-0 page-box-less\">", packageCodeDiv);
        } else if (cardTemp.contains("<div class=\"page-box page-box-A4 page-box-0\">")) {
            String packageCodeDiv = "<div class=\"page-box page-box-A4 page-box-0\"><div class=\"package-number\" style=\"position: absolute;width: 200px;height: 40px;top: 10px;right: 25%;margin-left: -100px;text-align: center;z-index: 99;\"><img src=\"data:image/png;base64," + packageCodeImg + "\" style=\"display: block; height: 28px; width: 100%\" /><p style=\"line-height: 1; font-size: 12px; margin: 0;\">" + packageCode + "</p></div>";
            cardTemp = cardTemp.replaceAll("<div class=\"page-box page-box-A4 page-box-0\">", packageCodeDiv);
        } else if (cardTemp.contains("<div class=\"page-box page-box-A4 page-box-0 page-box-less\">")) {
            String packageCodeDiv = "<div class=\"page-box page-box-A4 page-box-0 page-box-less\"><div class=\"package-number\" style=\"position: absolute;width: 200px;height: 40px;top: 10px;right: 25%;margin-left: -100px;text-align: center;z-index: 99;\"><img src=\"data:image/png;base64," + packageCodeImg + "\" style=\"display: block; height: 28px; width: 100%\" /><p style=\"line-height: 1; font-size: 12px; margin: 0;\">" + packageCode + "</p></div>";
            cardTemp = cardTemp.replaceAll("<div class=\"page-box page-box-A4 page-box-0 page-box-less\">", packageCodeDiv);
        }

        BasicAttachment cardAttachment = printCommonService.saveAttachmentHtml(examDetail.getSchoolId() + "|" + examDetailCourse.getCourseCode(), cardTemp, userId, cardPdfList, fileTempList);
        JSONObject object = new JSONObject();
        object.put("name", paperType);
        object.put("examDetailCourseId", examDetailCourse.getId());
        object.put("attachmentId", cardAttachment.getId());
        object.put("packageCode", packageCode);
        jsonArray.add(object);
        return cardAttachment;
    }

    /**
     * 获取班级名称
     *
     * @param examStudentDto
     * @return
     */
    private String getClassName(ExamStudentDto examStudentDto) {
        String clazzName = examStudentDto.getClazzName();
        if (StringUtils.isNotBlank(clazzName)) {
            return clazzName;
        }
        if (StringUtils.isNotBlank(examStudentDto.getClazzId())) {
            BasicClazz basicClazz = basicClazzService.getById(examStudentDto.getClazzId());
            clazzName = Objects.nonNull(basicClazz) ? basicClazz.getClazzName() : null;
        }
        if (StringUtils.isNotBlank(clazzName)) {
            return clazzName;
        }
        List<Map> mapList = JSONObject.parseArray(examStudentDto.getExtendFields(), Map.class);
        for (Map map : mapList) {
            if (Objects.equals("className", map.get("code").toString())) {
                return map.get("value").toString();
            }
        }
        return null;
    }
}
