package com.qmth.jkserver.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dto.FileDto;
import com.qmth.jkserver.enums.YunExamTypeEnum;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.params.callApi.SaveExamParams;
import com.qmth.jkserver.params.callApi.SaveStudentParams;
import com.qmth.jkserver.params.callApi.SaveSubjectParams;
import com.qmth.jkserver.params.callApi.fileUpload.JsonFileParams;
import com.qmth.jkserver.params.callApi.fileUpload.PaperFileParams;
import com.qmth.jkserver.service.*;
import com.qmth.jkserver.util.Base64Util;
import com.qmth.jkserver.util.FileStoreUtil;
import com.qmth.jkserver.util.JacksonUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 机考数据中心联调云阅卷流程模拟实现类（测试无误后移植到异步线程）
 * @Author: CaoZixuan
 * @Date: 2021-05-12
 */
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class JointFlowSimulationServiceImpl implements JointFlowSimulationService {
//    @Resource
//    MongoOperations mongoTemplate;

    @Resource
    @Lazy
    JkExamPlanService examPlanService;

    @Resource
    ExamPaperTempService examPaperTempService;

    @Resource
    ExamStudentService examStudentService;

    @Resource
    ExamStudentAnswerService examStudentAnswerService;

    @Resource
    CallYunMarkApiService callYunMarkApiService;

    @Resource
    ExamTaskService examTaskService;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    FileStoreUtil fileStoreUtil;

    @Override
    public Map<String, Object> saveYunExam(Map<String, Object> map) throws IOException, IllegalAccessException {
        ExamTask examTask = (ExamTask) map.get(SystemConstant.TASK);
        User user = (User) map.get(SystemConstant.USER);
        String jkExamCode = examTask.getExamCode();
        Long schoolId = (Long) map.get(SystemConstant.SCHOOL_ID);

        List<ExamPlan> examPlanDatasource = examPlanService.findExamPlanAllByTask();
        List<ExamPlan> examPlanList = examPlanDatasource.stream().filter(e -> jkExamCode.equals(e.getExamCode())).collect(Collectors.toList());
        if (examPlanList.size() != 1) {
            throw new JkServerException("机考考试获取异常");
        }
        ExamPlan examPlan = examPlanList.get(0);
        SaveExamParams saveExamParams = new SaveExamParams();
        saveExamParams.setCode(jkExamCode);
        saveExamParams.setName(examPlan.getName());
//        Date jkStartTime = examPlan.getStartTime();
        Long jkStartTime = examPlan.getStartTime();
//        saveExamParams.setExamTime(DateFormatUtils.format(jkStartTime, SystemConstant.DEFAULT_DATE_PATTERN));
        saveExamParams.setExamTime(DateFormatUtils.format(new Date(jkStartTime), SystemConstant.DEFAULT_DATE_PATTERN));
        saveExamParams.setType(YunExamTypeEnum.MULTI_MEDIA.getCode());
        int yunExamId = callYunMarkApiService.callExamSaveApi(saveExamParams, this.searchKeyAndSecretByJKExamCode(jkExamCode), schoolId);
        if (yunExamId == 0) {
            // 云阅卷考试保存失败 ： 不需要处理
            throw new JkServerException("调用云阅卷保存考试失败");
        }
        // 云阅卷考试保存成功 ： 任务完成数加一并把获得的云阅卷考试id存在map中传递 更新任务进度和机考考试信息
        map.put("yunExamId", yunExamId);
        examTaskService.updateExamTask(examTask, user);
        examPlanService.saveExamPlanByTask(jkExamCode, examTask);
        return map;
    }

    @Override
    public Map<String, Object> saveYunSubject(Map<String, Object> map) throws Exception {
        ExamTask examTask = (ExamTask) map.get(SystemConstant.TASK);
        User user = (User) map.get(SystemConstant.USER);
        Long schoolId = (Long) map.get(SystemConstant.SCHOOL_ID);
        BigDecimal totalProgress = examTask.getTotalProgress();
        AtomicInteger completeProgress;

        int yunExamId = (int) map.get(SystemConstant.YUN_EXAM_ID);
        String jkExamCode = examTask.getExamCode();
        // 查询该任务下 未同步的试卷
        List<ExamPaperTemp> examPaperTempList = examPaperTempService.findExamCourseAllByTask(jkExamCode)
                .stream().filter(e -> e.getTaskSyncResult() == null || !e.getTaskSyncResult()).collect(Collectors.toList());

        FileDto paperFileDto = examPaperTempService.getPaperAnswerJsonFile(jkExamCode);
        Map<Long, Attachment> attachmentMap = new HashMap<>();
        // 作答考生正常处理
        for (ExamPaperTemp examPaperTemp : examPaperTempList) {
            List<ExamStudentAnswer> examStudentAnswerDatasource = examStudentAnswerService.findByExamCode(jkExamCode, examPaperTemp.getCourseCode());
            Map<Long, ExamStudentAnswer> answerMap = examStudentAnswerDatasource.stream().collect(Collectors.toMap(k -> k.getId(), Function.identity(), (dto1, dto2) -> dto1));

            List<ExamStudentAnswer> examStudentAnswers = (List<ExamStudentAnswer>) map.get("examStudentAnswerList");
            examStudentAnswers = examStudentAnswerDatasource.stream().filter(s -> answerMap.containsKey(s.getId())).collect(Collectors.toList());
            FileDto studentAnswerFileDto = examPaperTempService.getExamStudentAnswerJsonFile(jkExamCode, examStudentAnswers, attachmentMap);

            List<String> willDeletePath = new ArrayList<>();
            // 组装待删除的文件路径集合
            if (Objects.nonNull(paperFileDto) && Objects.nonNull(paperFileDto.getDeletePaths())) {
                willDeletePath.addAll(paperFileDto.getDeletePaths());
            }
            if (Objects.nonNull(studentAnswerFileDto) && Objects.nonNull(studentAnswerFileDto.getDeletePaths())) {
                willDeletePath.addAll(studentAnswerFileDto.getDeletePaths());
            }
            map.put(SystemConstant.WILL_DELETE_PATH, willDeletePath);

            // 获取考试下的试卷结构、试卷标准答案、考生作答信息资源
            List<File> paperAndAnswerFileDatasource = paperFileDto.getFileList();
//        List<File> studentAnswerFileDatasource = studentAnswerFileDto.getFileList();

            // 循环试卷
            String courseCode = examPaperTemp.getCourseCode();
            String courseName = this.findCourseNameByCourseCode(jkExamCode, courseCode);
            String paperId = examPaperTemp.getPaperId();
            String yunSubjectCode = courseCode + SystemConstant.JOINT_MARK + paperId;

            SaveSubjectParams saveSubjectParams = new SaveSubjectParams();
            saveSubjectParams.setExamId(yunExamId);
            saveSubjectParams.setCode(yunSubjectCode);
            saveSubjectParams.setName(courseName);
            String updateTime = callYunMarkApiService.callSubjectSaveApi(saveSubjectParams, this.searchKeyAndSecretByJKExamCode(jkExamCode), schoolId);
            if (updateTime != null && updateTime.length() > 0 && !updateTime.equals("null")) {
                List<File> paperFileList = paperAndAnswerFileDatasource.stream()
                        .filter(e -> (yunSubjectCode + SystemConstant.JSON_PREFIX).equals(e.getName())).collect(Collectors.toList());
                if (paperFileList.size() != 1) {
                    throw new JkServerException("没有找到试卷编号为[" + yunSubjectCode + "]的试卷文件");
                }
                File paperFile = paperFileList.get(0);
                //解析试卷
                Map<String, Object> jsonMap = this.disposeQuestionUrl(paperFile);
                IOUtils.write(JacksonUtil.parseJson(jsonMap).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(paperFile));
                // 上传试卷结构和答案
                this.savePaperAndAnswer(map, yunExamId, yunSubjectCode, paperFile);

                List<LinkedMultiValueMap<String, File[]>> linkedMultiValueMapList = studentAnswerFileDto.getLinkedMultiValueMapList();
                //加入不同批次同科目处理
                for (int i = 0; i < linkedMultiValueMapList.size(); i++) {
                    List<File> studentAnswerFileDatasource = new ArrayList<>();
                    LinkedMultiValueMap<String, File[]> finalBatchIdFile = linkedMultiValueMapList.get(i);
                    Set<String> keySet = finalBatchIdFile.keySet();
                    for (String key : keySet) {
                        //根据key取出分组后list
                        List<File[]> files = finalBatchIdFile.get(key);
                        for (File[] f : files) {
                            studentAnswerFileDatasource.addAll(Arrays.asList(f));
                        }
                        // 保存学生信息
                        List<ExamStudentAnswer> examStudentAnswerList = examStudentAnswerDatasource.stream()
                                .filter(e -> {
                                    ExamStudent examStudent = examStudentService.getById(e.getStudentId());
                                    if (courseCode.equals(examStudent.getCourseCode()) &&
//                                            courseName.equals(examStudent.getCourseName()) &&
                                            !e.getIsAbsent() &&
                                            paperId.equals(e.getPaperId()) &&
                                            Objects.equals(examStudent.getBatchId(), key)
                                            && (e.getTaskSyncResult() == null || !e.getTaskSyncResult())
                                    ) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                }).collect(Collectors.toList());
                        map = this.saveYunExamStudent(map, yunExamId, examStudentAnswerList, this.getStudentAnswerFileList(yunSubjectCode, studentAnswerFileDatasource));
                    }
                }
                // 科目循环体下操作都成功了 任务数 + 1 并更新试卷同步状态
                examTask = (ExamTask) map.get(SystemConstant.TASK);
                completeProgress = new AtomicInteger(examTask.getCompleteProgress());
                completeProgress.addAndGet(2);
                examTask.setCompleteProgress(completeProgress.get());
                examTask.setProgress(this.calculateProgress(completeProgress, totalProgress));
                examTaskService.updateExamTask(examTask, user);

//                examPaperTemp.setExamTask(examTask);
                examPaperTemp.setExamTaskId(examTask.getId());
                examPaperTemp.setTaskSyncResult(true);
                examPaperTempService.saveOrUpdate(examPaperTemp);
//                mongoTemplate.save(examPaperTemp);
            } else {
                // 单纯创建科目失败
                throw new JkServerException("试卷创建失败");
            }
            // 未作答考生处理
            // 未同步的缺考考生数据集
            List<ExamStudentAnswer> examStudentAnswerList = examStudentAnswerDatasource.stream()
                    .filter(e -> e.getIsAbsent() && (e.getTaskSyncResult() == null || !e.getTaskSyncResult())).collect(Collectors.toList());

            // 处理因为缺考学生太多，进度的‘无效显示’问题
            for (int skip = 0; skip < examStudentAnswerList.size(); skip = skip + SystemConstant.SYNC_DATA_LIMIT) {
                List<ExamStudentAnswer> cellList = examStudentAnswerList.stream().skip(skip).limit(SystemConstant.SYNC_DATA_LIMIT).collect(Collectors.toList());
                map = this.saveYunExamStudent(map, yunExamId, cellList, null);
                examTask = (ExamTask) map.get(SystemConstant.TASK);
                completeProgress = new AtomicInteger(examTask.getCompleteProgress());
                examTask.setProgress(this.calculateProgress(completeProgress, totalProgress));
                examTaskService.updateExamTask(examTask, user);
            }
        }
        return map;
    }

    @Override
    public Map<String, Object> saveYunExamStudent(Map<String, Object> map, int yunExamId, List<ExamStudentAnswer> examStudentAnswerList, List<File> studentAnswerFileDatasource) throws IOException, IllegalAccessException {
        ExamTask examTask = (ExamTask) map.get(SystemConstant.TASK);
        String jkExamCode = examTask.getExamCode();
        Long schoolId = (Long) map.get(SystemConstant.SCHOOL_ID);

        for (ExamStudentAnswer examStudentAnswer : examStudentAnswerList) {
            ExamStudent examStudent = examStudentService.getById(examStudentAnswer.getStudentId());
            String courseCode = examStudent.getCourseCode();
            String courseName = examStudent.getCourseName();
            String ticketNo = examStudent.getTicketNo();
//            String[] ticketNoArr = {"1701001","1701002","1701003","1701004","1701005","1701006","1701010"};
//            if (!Arrays.asList(ticketNoArr).contains(ticketNo)){
//                continue;
//            }
            String paperId = examStudentAnswer.getPaperId();
            String paperCode = this.strIsNull(paperId) ? courseCode : courseCode + SystemConstant.JOINT_MARK + paperId;
            String examNumber = this.strIsNull(paperId) ? courseCode + SystemConstant.JOINT_MARK + ticketNo : courseCode + SystemConstant.JOINT_MARK + paperId + SystemConstant.JOINT_MARK + ticketNo;

            String studentCode = examStudent.getIdcard();
            String studentName = examStudent.getName();
            String placeCode = examStudent.getPlaceCode();
            String roomCode = examStudent.getRoomCode();
            boolean isAbsent = examStudentAnswer.getIsAbsent();

            SaveStudentParams saveStudentParams = new SaveStudentParams();
            saveStudentParams.setExamId(yunExamId);
            saveStudentParams.setExamNumber(examNumber);
            saveStudentParams.setStudentCode(studentCode);
            saveStudentParams.setName(studentName);
            saveStudentParams.setCollege(SystemConstant.VALUE_OF_BLANK_REQUIRED_FIELD);
            saveStudentParams.setClassName(SystemConstant.VALUE_OF_BLANK_REQUIRED_FIELD);
            saveStudentParams.setTeacher(SystemConstant.VALUE_OF_BLANK_REQUIRED_FIELD);
            saveStudentParams.setSubjectCode(paperCode);
            saveStudentParams.setSubjectName(courseName);
            saveStudentParams.setExamSite(placeCode);
            saveStudentParams.setExamRoom(roomCode);
            String updateTime = callYunMarkApiService.callStudentSaveApi(saveStudentParams, this.searchKeyAndSecretByJKExamCode(jkExamCode), schoolId);

            if (updateTime != null && updateTime.length() > 0 && !updateTime.equals("null")) {
                if (!isAbsent && studentAnswerFileDatasource != null && studentAnswerFileDatasource.size() > 0) {
                    List<File> thisJsonList = studentAnswerFileDatasource.stream()
                            .filter(e -> (ticketNo + SystemConstant.JSON_PREFIX).equals(e.getName())).collect(Collectors.toList());
                    if (thisJsonList.size() != 1) {
                        System.out.println("result : " + thisJsonList);
//                        throw new JkServerException("未找到试卷编号为[" + courseCode + "]、准考证号为[" + ticketNo + "]的考生作答数据文件");
                        continue;
                    }
                    map = this.saveStudentJson(map, yunExamId, examNumber, thisJsonList.get(0));
                    examStudentAnswer.setTaskSyncResult(true);
                }
                // 考生创建完毕同时有作答的也生成完毕了 考生上传成功 任务完成数++
                AtomicInteger completeProgress = new AtomicInteger(examTask.getCompleteProgress());
                completeProgress.incrementAndGet();
                examTask.setCompleteProgress(completeProgress.get());
//                examStudentAnswer.setTaskSyncResult(true);
//                examStudentAnswer.setExamTask(examTask);
//                mongoTemplate.save(examStudentAnswer);
                examStudentAnswer.setExamTaskId(examTask.getId());
                examStudentAnswerService.saveOrUpdate(examStudentAnswer);
            } else {
                throw new JkServerException("学生信息生成失败");
            }
        }
        return map;
    }

    @Override
    public Map<String, Object> savePaperAndAnswer(Map<String, Object> map, int yunExamId, String subjectCode, File file) throws IOException, IllegalAccessException {
        ExamTask examTask = (ExamTask) map.get(SystemConstant.TASK);
        Long schoolId = (Long) map.get(SystemConstant.SCHOOL_ID);
        String jkExamCode = examTask.getExamCode();

        PaperFileParams paperFileParams = new PaperFileParams();
        paperFileParams.setExamId(yunExamId);
        paperFileParams.setSubjectCode(subjectCode);
        paperFileParams.setFile(file);
        paperFileParams.setFormat("json");
        // 调用云阅卷上传附件接口
        callYunMarkApiService.callFileUploadApi(paperFileParams, this.searchKeyAndSecretByJKExamCode(jkExamCode), schoolId);
        return map;
    }

    @Override
    public Map<String, Object> saveStudentJson(Map<String, Object> map, int yunExamId, String examNumber, File file) throws IOException, IllegalAccessException {
        ExamTask examTask = (ExamTask) map.get(SystemConstant.TASK);
        Long schoolId = (Long) map.get(SystemConstant.SCHOOL_ID);
        String jkExamCode = examTask.getExamCode();

        JsonFileParams jsonFileParams = new JsonFileParams();
        jsonFileParams.setExamId(yunExamId);
        jsonFileParams.setExamNumber(examNumber);
        jsonFileParams.setFile(file);
        // 调用云阅卷上传附件接口
        callYunMarkApiService.callFileUploadApi(jsonFileParams, this.searchKeyAndSecretByJKExamCode(jkExamCode), schoolId);

        AtomicInteger completeProgress = new AtomicInteger(examTask.getCompleteProgress());
        completeProgress.incrementAndGet();
        examTask.setCompleteProgress(completeProgress.get());
        return map;
    }

    @Override
    public Map<String, String> searchKeyAndSecretByJKExamCode(String jkExamCode) {
        List<ExamPlan> examPlanDatasource = examPlanService.findExamPlanAllByTask();
        List<ExamPlan> examPlanList = examPlanDatasource.stream().filter(e -> jkExamCode.equals(e.getExamCode())).collect(Collectors.toList());
        if (examPlanList.size() != 1) {
            throw new JkServerException("根据考试编号[" + jkExamCode + "]获取考试信息失败");
        }

        ExamPlan examPlan = examPlanList.get(0);
//        String key = examPlan.getAccessKey();
//        String secret = examPlan.getAccessSecret();
        BasicSchool basicSchool = commonCacheService.schoolCache(examPlan.getSchoolId());
        Optional.ofNullable(basicSchool).orElseThrow(() -> new JkServerException("学校数据为空"));
        String key = basicSchool.getAccessKey();
        String secret = basicSchool.getAccessSecret();
        if (SystemConstant.isOneNull(key, secret)) {
            throw new JkServerException("考试编号为[" + jkExamCode + "]的考试缺少key或secret");
        }

        Map<String, String> map = new HashMap<>();
        map.put(SystemConstant.ACCESS_KEY, key);
        map.put(SystemConstant.ACCESS_SECRET, secret);

        return map;
    }

    @Override
    public void cleanExamDataByExamCode(String examCode) {
        // 1.清除任务数据
//        Query taskQuery = new Query();
//        taskQuery.addCriteria(Criteria.where("examCode").is(examCode));
////        List<ExamTask> examTaskList = mongoTemplate.find(taskQuery,ExamTask.class);
//        mongoTemplate.findAllAndRemove(taskQuery, ExamTask.class);
        QueryWrapper<ExamTask> examTaskQueryWrapper = new QueryWrapper<>();
        examTaskQueryWrapper.lambda().eq(ExamTask::getExamCode, examCode);
        examTaskService.remove(examTaskQueryWrapper);

        // 2.更新学生作答同步记录
        List<ExamStudentAnswer> examStudentAnswerList = examStudentAnswerService.findByExamCode(examCode, null);
        for (ExamStudentAnswer examStudentAnswer : examStudentAnswerList) {
            examStudentAnswer.setTaskSyncResult(false);
//            examStudentAnswer.setExamTask(null);
//            mongoTemplate.save(examStudentAnswer);
            examStudentAnswer.setExamTaskId(null);
            examStudentAnswerService.saveOrUpdate(examStudentAnswer);
        }

        // 3.清除试卷同步记录
        List<ExamPaperTemp> examPaperTempList = examPaperTempService.findExamCourseAllByTask(examCode);
        for (ExamPaperTemp examPaperTemp : examPaperTempList) {
            examPaperTemp.setTaskSyncResult(false);
//            examPaperTemp.setExamTask(null);
//            mongoTemplate.save(examPaperTemp);
            examPaperTemp.setExamTaskId(null);
            examPaperTempService.saveOrUpdate(examPaperTemp);
        }

        // 4.清除考试计划同步记录
        List<ExamPlan> examPlanList = examPlanService.findExamPlanAllByTask();
        ExamPlan examPlan = examPlanList.stream().filter(e -> e.getExamCode().equals(examCode)).collect(Collectors.toList()).get(0);
//        examPlan.setExamTask(null);
//        mongoTemplate.save(examPlan);
        examPlan.setExamTaskId(null);
        examPlanService.saveOrUpdate(examPlan);
    }

    /**
     * 根据课程代码查询课程名称
     *
     * @param examCode   考试代码
     * @param courseCode 课程代码
     * @return 课程名称
     */
    private String findCourseNameByCourseCode(String examCode, String courseCode) {
        List<ExamStudent> examStudentDatasource = examStudentService.findByExamCode(examCode);
        List<ExamStudent> examStudentList = examStudentDatasource.stream().filter(e -> courseCode.equals(e.getCourseCode()))
                .collect(Collectors.toList());
        if (examStudentList.size() == 0) {
            throw new JkServerException("未找到课程");
        }
        return examStudentList.get(0).getCourseName();
    }

    /**
     * 判断字符串是否为空
     *
     * @param str 字符串
     * @return 结果
     */
    private boolean strIsNull(String str) {
        return str == null || str.length() == 0 || "null".equals(str);
    }

    /**
     * 计算任务当前进度
     *
     * @param completeProgress 任务已完成进度数
     * @param totalProgress    总任务进度
     * @return 任务进度百分比 -》 98
     */
    private BigDecimal calculateProgress(AtomicInteger completeProgress, BigDecimal totalProgress) {
        BigDecimal progress = new BigDecimal(completeProgress.get()).divide(totalProgress, 2, BigDecimal.ROUND_HALF_UP);
        return progress.multiply(SystemConstant.RATE_BIG_DECIMAL);
    }

    /**
     * 查找科目下学生作答答案
     *
     * @param yunSubjectCode              机考数据中心'科目编号_试卷id'即云阅卷试卷编号
     * @param studentAnswerFileDatasource 考生作答答案包（按试卷装）数据源
     * @return 该科目编号下考生的作答答案集合
     */
    private List<File> getStudentAnswerFileList(String yunSubjectCode, List<File> studentAnswerFileDatasource) {
        List<File> tempList = studentAnswerFileDatasource.stream()
                .filter(e -> yunSubjectCode.equals(e.getName()))
                .collect(Collectors.toList());
        if (tempList.size() > 1) {
            throw new JkServerException("同一科目下存在多个答案包");
        } else if (tempList.size() < 1) {
            return null;
        } else {
            return Arrays.asList(Objects.requireNonNull(tempList.get(0).listFiles()));
        }
    }

    /**
     * 解析试卷
     *
     * @param paperFile
     * @return
     * @throws Exception
     */
    public Map<String, Object> disposeQuestionUrl(File paperFile) throws Exception {
        Map<String, Object> jsonMap = new LinkedHashMap<>();
        byte[] bytes = IOUtils.toByteArray(new FileInputStream(paperFile));
        jsonMap = JSONArray.parseObject(new String(bytes, SystemConstant.CHARSET_NAME), Map.class);
        if (!CollectionUtils.isEmpty(jsonMap)) {
            JSONArray structdetails = (JSONArray) jsonMap.get("details");
            if (Objects.nonNull(structdetails) && structdetails.size() > 0) {
                for (int i = 0; i < structdetails.size(); i++) {
                    JSONArray structdetailquestions = structdetails.getJSONObject(i).getJSONArray("questions");
                    if (Objects.nonNull(structdetailquestions) && structdetailquestions.size() > 0) {
                        for (int j = 0; j < structdetailquestions.size(); j++) {
                            JSONObject structquestion = structdetailquestions.getJSONObject(j);
                            JSONObject body = structquestion.getJSONObject(SystemConstant.BODY);
                            this.resolveImageAndAudio(paperFile, body);
                            JSONArray options = structquestion.getJSONArray("options");
                            if (Objects.nonNull(options) && options.size() > 0) {
                                for (int k = 0; k < options.size(); k++) {
                                    JSONObject option = options.getJSONObject(k);
                                    if (Objects.nonNull(option)) {
                                        JSONObject optionBody = option.getJSONObject(SystemConstant.BODY);
                                        this.resolveImageAndAudio(paperFile, optionBody);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return jsonMap;
    }

    /**
     * base64图片和音频
     *
     * @param paperFile
     * @param body
     */
    public void resolveImageAndAudio(File paperFile, JSONObject body) {
        if (Objects.nonNull(body)) {
            JSONArray sections = body.getJSONArray("sections");
            if (Objects.nonNull(sections) && sections.size() > 0) {
                for (int k = 0; k < sections.size(); k++) {
                    JSONObject block = sections.getJSONObject(k);
                    if (block != null) {
                        JSONArray blocks = block.getJSONArray("blocks");
                        if (Objects.nonNull(blocks) && blocks.size() > 0) {
                            for (int m = 0; m < blocks.size(); m++) {
                                JSONObject blockInfo = blocks.getJSONObject(m);
                                String type = blockInfo.getString(SystemConstant.TYPE);
                                String value = blockInfo.getString("value");
                                File attachmentDir = new File(paperFile.getParentFile().getParentFile(), "attachment" + File.separator + value);
                                if (("image".equals(type) || "audio".equals(type)) && StringUtils.isNotBlank(value) && !value.toLowerCase()
                                        .startsWith("https://") && !value.toLowerCase().startsWith("http://")) {
                                    if ("image".equals(type)) {
                                        if (value.contains("data:image")) {
                                            blockInfo.put("value", value);
                                        } else {
                                            String base64Str = Base64Util.imageToBase64(attachmentDir);
                                            blockInfo.put("value", base64Str);
                                        }
                                    } else if ("audio".equals(type)) {
                                        if (value.contains("data:audio")) {
                                            blockInfo.put("value", value);
                                        } else {
                                            String base64Str = Base64Util.audioToBase64(attachmentDir);
                                            blockInfo.put("value", base64Str);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
