package com.qmth.themis.business.templete.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.reflect.TypeToken;
import com.qmth.themis.business.annotation.ExcelDynamicExport;
import com.qmth.themis.business.annotation.ExcelNotExport;
import com.qmth.themis.business.annotation.ExcelNote;
import com.qmth.themis.business.cache.bean.ExamCacheBean;
import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.ExcelDto;
import com.qmth.themis.business.dto.MarkResultSimpleExportDto;
import com.qmth.themis.business.dto.MarkResultStandardExportDto;
import com.qmth.themis.business.dto.response.MarkResultDto;
import com.qmth.themis.business.entity.TOeExamAnswer;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.entity.TSyncExamStudentScore;
import com.qmth.themis.business.enums.AnswerTypeEnum;
import com.qmth.themis.business.enums.QuestionTypeEnum;
import com.qmth.themis.business.enums.TaskStatusEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.templete.TaskExportCommon;
import com.qmth.themis.business.templete.TaskExportTemplete;
import com.qmth.themis.business.templete.service.TempleteLogicService;
import com.qmth.themis.common.contanst.Constants;
import com.qmth.themis.common.util.FileUtil;
import com.qmth.themis.common.util.GsonUtil;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 成绩标准版导出任务
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/10/20
 */
@Service
public class TaskMarkResultStandardExportTemplete implements TaskExportTemplete {

    private final static Logger log = LoggerFactory.getLogger(TaskMarkResultStandardExportTemplete.class);

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TempleteLogicService templeteLogicService;

    @Resource
    TOeExamAnswerService tOeExamAnswerService;

    @Resource
    TEExamPaperService teExamPaperService;

    @Resource
    TEExamService teExamService;

    @Resource
    TOeExamRecordService tOeExamRecordService;

    @Resource
    TSyncExamStudentScoreService tSyncExamStudentScoreService;

    /**
     * 考场导出模版
     *
     * @param map
     * @return
     */
    @Override
    public Result exportTask(Map<String, Object> map) throws IOException {
        log.info("开始导出成绩标准版数据");
        long start = System.currentTimeMillis();
        TaskExportCommon taskExportCommon = new TaskExportCommon(map);
        taskExportCommon.init();
        taskExportCommon.setTxtList(new ArrayList());
        StringJoiner stringJoiner = null;
        String zipPath = null;
        File zip = null;
        List<File> files = null;
        int finalSize = 0, min = 0, line = 0;
        try {
            taskExportCommon.getTxtList()
                    .add(DateUtil.format(new Date(), Constants.DEFAULT_DATE_PATTERN) + "->开始准备处理导出的成绩标准版数据");
            Long examId = (Long) map.get(SystemConstant.EXAM_ID);
            Long activityId = (Long) map.get(SystemConstant.ACTIVITY_ID);
            String identity = (String) map.get("identity");
            String name = (String) map.get(SystemConstant.NAME);
            String courseCode = (String) map.get(SystemConstant.COURSE_CODE);

            List<MarkResultSimpleExportDto> markResultSimpleExportDtoList = null;
            int pageSize = SystemConstant.MAX_QUERY_SIZE, pageNumber = SystemConstant.MIN_QUERY_SIZE;
            IPage<MarkResultSimpleExportDto> markResultQueryExportIpage = teExamStudentService.markResultQueryExportIpage(new Page<>(pageNumber, pageSize), examId, activityId, identity, name, courseCode);
            while (Objects.nonNull(markResultQueryExportIpage) && markResultQueryExportIpage.getRecords().size() > 0) {
                markResultSimpleExportDtoList = Objects.isNull(markResultSimpleExportDtoList) ? new ArrayList<>(markResultQueryExportIpage.getRecords().size() * 10) : markResultSimpleExportDtoList;
                pageNumber++;
                markResultSimpleExportDtoList.addAll(markResultQueryExportIpage.getRecords());
                markResultQueryExportIpage = teExamStudentService.markResultQueryExportIpage(new Page<>(pageNumber, pageSize), examId, activityId, identity, name, courseCode);
            }

            Map<Long, Map<String, Double>> subjectiveScoreMap = null;
            if (!CollectionUtils.isEmpty(markResultSimpleExportDtoList)) {
                Set<String> examRecordIdsSet = new LinkedHashSet<>(markResultSimpleExportDtoList.size());
                for (MarkResultSimpleExportDto markResultSimpleExportDto : markResultSimpleExportDtoList) {
                    MarkResultDto markResultDto = GsonUtil
                            .fromJson(GsonUtil.toJson(markResultSimpleExportDto), MarkResultDto.class);
                    if (Objects.nonNull(markResultDto.getExamId())) {
                        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(markResultDto.getExamId());
                        TOeExamRecord tOeExamRecord = tOeExamRecordService
                                .findMarkResult(markResultDto, examCacheBean.getRecordSelectStrategy());
                        if (Objects.nonNull(tOeExamRecord)) {
                            ExamPaperCacheBean examPaperCacheBean = teExamPaperService.getExamPaperCacheBean(tOeExamRecord.getPaperId());
                            examRecordIdsSet.add(String.valueOf(tOeExamRecord.getId()));
                            markResultSimpleExportDto.setObjectiveScore(Objects.isNull(tOeExamRecord.getObjectiveScore()) ? "0" : String.valueOf(tOeExamRecord.getObjectiveScore()));
                            markResultSimpleExportDto.setRecordId(String.valueOf(tOeExamRecord.getId()));
                            markResultSimpleExportDto.setPaperId(tOeExamRecord.getPaperId());
                            if (Objects.nonNull(examPaperCacheBean)) {
                                markResultSimpleExportDto.setPaperName(examPaperCacheBean.getName());
                            }
                            markResultSimpleExportDto.setSubjectiveScore(Objects.isNull(markResultSimpleExportDto.getSubjectiveScore()) ? "0" : String.valueOf(markResultSimpleExportDto.getSubjectiveScore()));
                            markResultSimpleExportDto.setSumScore(String.valueOf(Double.parseDouble(markResultSimpleExportDto.getObjectiveScore()) + Double.parseDouble(markResultSimpleExportDto.getSubjectiveScore())));
                            if (Objects.nonNull(tOeExamRecord.getFirstStartTime())) {
                                markResultSimpleExportDto.setFirstStartTime(DateUtil.format(new Date(tOeExamRecord.getFirstStartTime()), SystemConstant.DEFAULT_DATE_PATTERN));
                            }
                            if (Objects.nonNull(tOeExamRecord.getFinishTime())) {
                                markResultSimpleExportDto.setFinishTime(DateUtil.format(new Date(tOeExamRecord.getFinishTime()), SystemConstant.DEFAULT_DATE_PATTERN));
                            }
                        }
                    }
                }
                if (!CollectionUtils.isEmpty(examRecordIdsSet)) {
                    Map<String, MarkResultSimpleExportDto> markResultSimpleExportDtoMap = markResultSimpleExportDtoList.stream().collect(
                            Collectors.toMap(MarkResultSimpleExportDto::getRecordId, Function.identity(), (dto1, dto2) -> dto1));

                    //获取云阅卷同步成绩
                    List<TSyncExamStudentScore> tSyncExamStudentScoreList = tSyncExamStudentScoreService.findByExamRecordIds(examRecordIdsSet);
                    if (!CollectionUtils.isEmpty(tSyncExamStudentScoreList)) {
                        subjectiveScoreMap = new LinkedHashMap<>(tSyncExamStudentScoreList.size());
                        for (TSyncExamStudentScore t : tSyncExamStudentScoreList) {
                            MarkResultSimpleExportDto markResultSimpleExportDto = markResultSimpleExportDtoMap.get(t.getExamNumber());
                            if (Objects.nonNull(markResultSimpleExportDto)) {
                                if (Objects.nonNull(t.getSubjectiveScoreDetail()) && !Objects.equals(t.getSubjectiveScoreDetail().trim(), "")) {
                                    JSONArray subjectiveScoreDetailJsonArray = JSONArray.parseArray(t.getSubjectiveScoreDetail());
                                    Map<String, Double> tOeExamAnswerMap = new LinkedHashMap<>(subjectiveScoreDetailJsonArray.size());
                                    for (int i = 0; i < subjectiveScoreDetailJsonArray.size(); i++) {
                                        JSONObject jsonObject = subjectiveScoreDetailJsonArray.getJSONObject(i);
                                        Integer mainNumber = jsonObject.getInteger("mainNumber");
                                        String subNumberStr = jsonObject.getString("subNumber");
                                        Integer subNumber = null, subIndex = null;
                                        if (Objects.nonNull(subNumberStr)) {
                                            String[] strs = StringUtils.split(subNumberStr, "-");
                                            subNumber = Integer.parseInt(strs[0]);
                                            if (strs.length > 1) {
                                                subIndex = Integer.parseInt(strs[1]);
                                            }
                                        }
                                        Double score = jsonObject.getDouble("score");
                                        String questionsTitle = String.valueOf(mainNumber);
                                        questionsTitle = Objects.nonNull(subNumber) ?
                                                questionsTitle + "_" + subNumber :
                                                questionsTitle;
                                        questionsTitle = Objects.nonNull(subIndex) ?
                                                questionsTitle + "_" + subIndex :
                                                questionsTitle;
                                        tOeExamAnswerMap.put(questionsTitle, score);
                                    }
                                    subjectiveScoreMap.put(Long.parseLong(t.getExamNumber()), tOeExamAnswerMap);
                                }
                                markResultSimpleExportDto.setSubjectiveScore(Objects.isNull(t.getSubjectiveScore()) ? "0" : String.valueOf(t.getSubjectiveScore()));
                                markResultSimpleExportDto.setSumScore(String.valueOf(Double.parseDouble(markResultSimpleExportDto.getObjectiveScore()) + Double.parseDouble(markResultSimpleExportDto.getSubjectiveScore())));
                            }
                        }
                    }
                }
            }
            List<MarkResultStandardExportDto> markResultStandardExportDtoList = GsonUtil.fromJson(GsonUtil.toJson(markResultSimpleExportDtoList),
                    new TypeToken<List<MarkResultStandardExportDto>>() {
                    }.getType());
            Map<Long, List<ExcelDto>> excelDtoMap = null;
            Map<Long, Map<String, Integer>> paperObjectiveAnswerMap = new HashMap<>();
            LinkedMultiValueMap<Long, ExcelDto> dynamicExcelHead = new LinkedMultiValueMap<>();
            LinkedMultiValueMap<Long, MarkResultStandardExportDto> markResultStandardExportDtoLinkedMultiValueMap = new LinkedMultiValueMap<>();
            List<MarkResultStandardExportDto> missMarkResultStandardExportDtoList = new LinkedList<>();
            if (!CollectionUtils.isEmpty(markResultStandardExportDtoList)) {
                for (MarkResultStandardExportDto m : markResultStandardExportDtoList) {
                    excelDtoMap = new HashMap<>();
                    Map<String, Integer> objectiveAnswerCacheBeanMap = null;
                    if (Objects.nonNull(m.getPaperId())) {//处理试卷
                        if (!paperObjectiveAnswerMap.containsKey(m.getPaperId())) {
                            objectiveAnswerCacheBeanMap = teExamPaperService.getPaperStructCacheBean(m.getPaperId());
                            paperObjectiveAnswerMap.put(m.getPaperId(), objectiveAnswerCacheBeanMap);
                            objectiveAnswerCacheBeanMap.forEach((k, v) -> {
//                                if (v != 6) {//套题暂不展现
                                String title = QuestionTypeEnum.convertToTitle(v) + k;
                                if (v >= 1 && v < 4) {
                                    ExcelDto excelAnswerDto = new ExcelDto(title + "作答");
                                    ExcelDto excelScoreDto = new ExcelDto(title + "得分");
                                    dynamicExcelHead.add(m.getPaperId(), excelAnswerDto);
                                    dynamicExcelHead.add(m.getPaperId(), excelScoreDto);
                                } else {
                                    ExcelDto excelScoreDto = new ExcelDto(title + "得分");
                                    dynamicExcelHead.add(m.getPaperId(), excelScoreDto);
                                }
//                                }
                            });
                        } else {
                            objectiveAnswerCacheBeanMap = paperObjectiveAnswerMap.get(m.getPaperId());
                        }
                    } else {
                        missMarkResultStandardExportDtoList.add(m);
                        continue;
                    }
                    if (Objects.nonNull(m.getRecordId())) {//处理考生答案
                        QueryWrapper<TOeExamAnswer> tOeExamAnswerQueryWrapper = new QueryWrapper<>();
                        tOeExamAnswerQueryWrapper.lambda().eq(TOeExamAnswer::getExamRecordId, Long.parseLong(m.getRecordId()));
                        List<TOeExamAnswer> tOeExamAnswerList = tOeExamAnswerService.list(tOeExamAnswerQueryWrapper);
                        for (TOeExamAnswer s : tOeExamAnswerList) {
                            String questionsTitle = String.valueOf(s.getMainNumber());
                            questionsTitle = Objects.nonNull(s.getSubNumber()) ?
                                    questionsTitle + "_" + s.getSubNumber() :
                                    questionsTitle;
                            questionsTitle = Objects.nonNull(s.getSubIndex()) ?
                                    questionsTitle + "_" + s.getSubIndex() :
                                    questionsTitle;
                            if (Objects.nonNull(s.getAnswer())) {
                                Integer structType = objectiveAnswerCacheBeanMap.get(questionsTitle);
                                if (Objects.nonNull(structType)) {
                                    String title = QuestionTypeEnum.convertToTitle(structType) + questionsTitle;
                                    String answer = null;
                                    ExcelDto excelAnswerDto = null;
                                    Double score = null;
                                    if (structType.intValue() == 1 || structType.intValue() == 2) {
                                        String string = s.getAnswer().replace("[", "").replace("]", "")
                                                .replaceAll(" ", "").replaceAll("\n", "");
                                        if (Objects.nonNull(string) && !Objects.equals(string, "")) {
                                            List<String> list = Arrays.asList(string.split(","));
                                            List<String> answerList = new ArrayList<>();
                                            for (String s1 : list) {
                                                answerList.add(AnswerTypeEnum.convertToTitle(s1.toUpperCase()));
                                            }
                                            answer = answerList.toString();
                                        }
                                        excelAnswerDto = new ExcelDto(title + "作答", answer);
                                        score = s.getScore();
                                    } else if (structType.intValue() == 3) {
                                        answer = AnswerTypeEnum
                                                .convertToTitle(s.getAnswer().replaceAll("\n", "").toUpperCase());
                                        excelAnswerDto = new ExcelDto(title + "作答", answer);
                                        score = s.getScore();
                                    }
                                    if (Objects.isNull(score) && !CollectionUtils.isEmpty(subjectiveScoreMap)) {
                                        Map<String, Double> tOeExamAnswerMap = subjectiveScoreMap.get(s.getExamRecordId());
                                        if (!CollectionUtils.isEmpty(tOeExamAnswerMap) && Objects.nonNull(tOeExamAnswerMap.get(questionsTitle))) {
                                            score = tOeExamAnswerMap.get(questionsTitle);
                                        }
                                    }
                                    ExcelDto excelScoreDto = new ExcelDto(title + "得分",
                                            Objects.nonNull(score) ? String.valueOf(score) : "0");
                                    List<ExcelDto> excelDtoList = null;
                                    if (!excelDtoMap.containsKey(m.getExamStudentId())) {
                                        excelDtoList = new ArrayList<>();
                                    } else {
                                        excelDtoList = excelDtoMap.get(m.getExamStudentId());
                                    }
                                    excelDtoList.add(excelAnswerDto);
                                    excelDtoList.add(excelScoreDto);
                                    excelDtoMap.put(m.getExamStudentId(), excelDtoList);
                                }
                            }
                        }
                    }
                    m.setAnswerExcetDto(excelDtoMap);
                    markResultStandardExportDtoLinkedMultiValueMap.add(m.getPaperId(), m);
                }
            }
            files = Objects.isNull(files) ? new ArrayList<>() : files;

            boolean oss = (boolean) taskExportCommon.getOssEnv().get(SystemConstant.OSS);
            stringJoiner = new StringJoiner("");
            StringJoiner excelSj = new StringJoiner("");
            if (!oss) {
                stringJoiner.add(SystemConstant.FILES_DIR).add(File.separator);
            }
            excelSj.add(SystemConstant.FILES_DIR).add(File.separator);
            LocalDateTime nowTime = LocalDateTime.now();
            stringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                    .add(String.format("%02d", nowTime.getDayOfMonth()));

            excelSj.add(String.valueOf(nowTime.getYear())).add(File.separator)
                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                    .add(String.format("%02d", nowTime.getDayOfMonth()));

            map = createExamStudentExcel(dynamicExcelHead, markResultStandardExportDtoLinkedMultiValueMap, map, files, taskExportCommon, excelSj);
            finalSize = Integer.parseInt(String.valueOf(map.get("finalSize")));
            min = Integer.parseInt(String.valueOf(map.get("min")));
            line = Integer.parseInt(String.valueOf(map.get("line")));
            map = createMissExamStudentExcel(missMarkResultStandardExportDtoList, finalSize, min, line, map, files, taskExportCommon, excelSj);
            finalSize = Integer.parseInt(String.valueOf(map.get("finalSize")));
            min = Integer.parseInt(String.valueOf(map.get("min")));
            line = Integer.parseInt(String.valueOf(map.get("line")));
            if (files.size() > 0) {
                StringBuilder stringBuilder = new StringBuilder(excelSj.toString());
                String uuid = SystemConstant.getNanoId();
                StringBuilder zipStringBuilder = new StringBuilder(stringJoiner.toString());
                zipPath = zipStringBuilder.append(File.separator).append(uuid).toString();
                zip = new File(stringBuilder.append(File.separator).append(uuid).append(".zip").toString());
                FileUtil.doZip(zip, files);
                taskExportCommon.getOssUtil().upload(false, zipPath, zip);
                files.add(zip);
            }
            long end = System.currentTimeMillis();
            log.info("导出成绩标准版数据结束,============耗时============:{}秒", (end - start) / 1000);
        } catch (Exception e) {
            log.error("导出报错", e);
            taskExportCommon.exception(line, e, taskExportCommon.getTxtList());
        } finally {
            //这里写入txt文件
            taskExportCommon.getTbTaskHistory().setStatus(TaskStatusEnum.FINISH);
            taskExportCommon.getTbTaskHistory().setSummary("共导出了" + finalSize + "条数据");
            taskExportCommon.getTbTaskHistory().setFinishTime(System.currentTimeMillis());
            taskExportCommon.getTxtList().removeAll(taskExportCommon.getTxtList().subList(1, taskExportCommon.getTxtList().size()));
            taskExportCommon.getTxtList().add(DateUtil.format(new Date(), Constants.DEFAULT_DATE_PATTERN) + "->数据导出完毕，" + taskExportCommon.getTbTaskHistory().getSummary());
            taskExportCommon.writeExportResultTxt(stringJoiner.toString(), taskExportCommon.getTxtList().toString(), zipPath);
            if (Objects.nonNull(files)) {
                for (File file : files) {
                    file.delete();
                }
            }
        }
        return ResultUtil.ok(true);
    }

    /**
     * 创建非缺考考生excel
     *
     * @param dynamicExcelHead
     * @param markResultStandardExportDtoLinkedMultiValueMap
     * @param map
     * @param files
     * @param taskExportCommon
     * @param excelSj
     * @return
     * @throws IOException
     */
    public Map<String, Object> createExamStudentExcel(LinkedMultiValueMap<Long, ExcelDto> dynamicExcelHead,
                                                      LinkedMultiValueMap<Long, MarkResultStandardExportDto> markResultStandardExportDtoLinkedMultiValueMap,
                                                      Map<String, Object> map, List<File> files,
                                                      TaskExportCommon taskExportCommon, StringJoiner excelSj) throws IOException {
        int finalSize = 0, min = 0, line = 0;
        SXSSFWorkbook wb = null;
        InputStream inputStream = null;
        ByteArrayOutputStream out = null;
        //开始根据卷型生成多个excel
        for (Map.Entry<Long, List<ExcelDto>> entry : dynamicExcelHead.entrySet()) {
            try {
                //创建excel
                wb = new SXSSFWorkbook();
                Sheet sheet = wb.createSheet("成绩统计标准版");
                CellStyle style = wb.createCellStyle();
                style.setAlignment(HorizontalAlignment.CENTER); // 水平居中格式
                style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
                Row row = sheet.createRow(0);
                Field[] fields = MarkResultStandardExportDto.class.getDeclaredFields();
                int num = 0;
                //绘制表头
                for (int i = 0; i < fields.length; i++) {
                    Field field = fields[i];
                    field.setAccessible(true);
                    Annotation annotation = field.getAnnotation(ExcelNote.class);
                    if (Objects.nonNull(annotation)) {
                        Cell cell = row.createCell(i);
                        cell.setCellValue(field.getAnnotation(ExcelNote.class).value());
                        cell.setCellStyle(style);
                        num = i;
                    }
                }
                num++;
                Map<String, Integer> position = new LinkedHashMap<>();

                //动态表头
                for (ExcelDto excelDto : entry.getValue()) {
                    Cell cell = row.createCell(num);
                    cell.setCellValue(excelDto.getTitle());
                    cell.setCellStyle(style);
                    sheet.setColumnWidth(num, 15 * 256);
                    position.put(excelDto.getTitle(), num);
                    num++;
                }
                List<MarkResultStandardExportDto> markResultStandardExportDtoTempList = markResultStandardExportDtoLinkedMultiValueMap.get(entry.getKey());
                int rowIndex = 0, cellIndex = 0, max = SystemConstant.MAX_EXPORT_SIZE, size = markResultStandardExportDtoTempList
                        .size();
                if (max >= size) {
                    max = size;
                }
                while (max <= size) {
                    List subList = markResultStandardExportDtoTempList.subList(min, max);
                    //绘制数据
                    for (int y = 0; y < subList.size(); y++) {
                        finalSize++;
                        line++;
                        rowIndex++;
                        MarkResultStandardExportDto markResultStandardExportDto = (MarkResultStandardExportDto) subList.get(y);
                        cellIndex = 0;
                        Row sxssfRow = sheet.createRow(rowIndex);
                        for (Field field : fields) {
                            field.setAccessible(true);
                            Annotation annotation = field.getAnnotation(ExcelNotExport.class);
                            if (Objects.isNull(annotation)) {
                                Annotation dynamicExport = field.getAnnotation(ExcelDynamicExport.class);
                                if (Objects.nonNull(dynamicExport)) {
                                    Map<Long, List<ExcelDto>> answerExcetDto = markResultStandardExportDto
                                            .getAnswerExcetDto();
                                    if (Objects.nonNull(answerExcetDto)) {
                                        List<ExcelDto> excelDtoList = answerExcetDto
                                                .get(markResultStandardExportDto.getExamStudentId());
                                        if (Objects.nonNull(excelDtoList) && excelDtoList.size() > 0) {
                                            excelDtoList.forEach(s -> {
                                                if (Objects.nonNull(s) && Objects.nonNull(s.getTitle()) && Objects.nonNull(position.get(s.getTitle()))) {
                                                    taskExportCommon.createExcelCell(sxssfRow, position.get(s.getTitle()), s.getContent(), style);
                                                }
                                            });
                                        }
                                    }
                                } else {
                                    taskExportCommon.createExcelCell(sxssfRow, cellIndex, field.get(markResultStandardExportDto), style);
                                    cellIndex++;
                                }
                            }
                        }
                    }
                    map.put("max", max);
                    map.put("min", min);
                    map.put("size", size);
                    map = templeteLogicService.execExportMarkResultSimpleLogic(map);
                    if (max == size) {
                        break;
                    }
                    min = max;
                    max += SystemConstant.MAX_EXPORT_SIZE;
                    if (max >= size) {
                        max = size;
                    }
                }
                //临时缓冲区
                out = new ByteArrayOutputStream();
                wb.write(out);
                byte[] bookByteAry = out.toByteArray();
                inputStream = new ByteArrayInputStream(bookByteAry);
                StringBuilder stringBuilder = new StringBuilder(excelSj.toString());
                File finalFile = new File(stringBuilder.append(File.separator).append(markResultStandardExportDtoTempList.get(0).getPaperId() + "_" + markResultStandardExportDtoTempList.get(0).getPaperName() + "_" + markResultStandardExportDtoTempList.get(0).getCourseName() + "_" + markResultStandardExportDtoTempList.get(0).getCourseCode()).append(SystemConstant.EXCEL_PREFIX).toString());
                if (!finalFile.exists()) {
                    finalFile.getParentFile().mkdirs();
                    finalFile.createNewFile();
                }
                FileUtils.copyInputStreamToFile(inputStream, finalFile);
                files.add(finalFile);
            } catch (Exception e) {
                log.error("生成excel报错", e);
                e.printStackTrace();
            } finally {
                if (Objects.nonNull(wb)) {
                    wb.dispose();
                }
                if (Objects.nonNull(inputStream)) {
                    inputStream.close();
                }
                if (Objects.nonNull(out)) {
                    out.flush();
                    out.close();
                }
            }
        }
        map.put("finalSize", finalSize);
        map.put("line", line);
        return map;
    }

    /**
     * 创建缺考考生excel
     *
     * @param missMarkResultStandardExportDtoList
     * @param finalSize
     * @param min
     * @param line
     * @param map
     * @param files
     * @param taskExportCommon
     * @param excelSj
     * @return
     * @throws IOException
     */
    public Map<String, Object> createMissExamStudentExcel(List<MarkResultStandardExportDto> missMarkResultStandardExportDtoList,
                                                          int finalSize, int min, int line,
                                                          Map<String, Object> map, List<File> files,
                                                          TaskExportCommon taskExportCommon, StringJoiner excelSj) throws IOException {
        SXSSFWorkbook wb = null;
        InputStream inputStream = null;
        ByteArrayOutputStream out = null;
        //开始生成缺考excel
        if (!CollectionUtils.isEmpty(missMarkResultStandardExportDtoList)) {
            try {
                //创建excel
                wb = new SXSSFWorkbook();
                Sheet sheet = wb.createSheet("成绩统计标准版_缺考考生");
                CellStyle style = wb.createCellStyle();
                style.setAlignment(HorizontalAlignment.CENTER); // 水平居中格式
                style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
                Row row = sheet.createRow(0);
                Field[] fields = MarkResultStandardExportDto.class.getDeclaredFields();
                //绘制表头
                for (int i = 0; i < fields.length; i++) {
                    Field field = fields[i];
                    field.setAccessible(true);
                    Annotation annotation = field.getAnnotation(ExcelNote.class);
                    if (Objects.nonNull(annotation)) {
                        Cell cell = row.createCell(i);
                        cell.setCellValue(field.getAnnotation(ExcelNote.class).value());
                        cell.setCellStyle(style);
                    }
                }
                int rowIndex = 0, cellIndex = 0, max = SystemConstant.MAX_EXPORT_SIZE, size = missMarkResultStandardExportDtoList.size();
                if (max >= size) {
                    max = size;
                }
                while (max <= size) {
                    List subList = missMarkResultStandardExportDtoList.subList(min, max);
                    //绘制数据
                    for (int y = 0; y < subList.size(); y++) {
                        finalSize++;
                        line++;
                        rowIndex++;
                        MarkResultStandardExportDto markResultStandardExportDto = (MarkResultStandardExportDto) subList.get(y);
                        cellIndex = 0;
                        Row sxssfRow = sheet.createRow(rowIndex);
                        for (Field field : fields) {
                            field.setAccessible(true);
                            Annotation annotation = field.getAnnotation(ExcelNotExport.class);
                            if (Objects.isNull(annotation)) {
                                taskExportCommon.createExcelCell(sxssfRow, cellIndex, field.get(markResultStandardExportDto), style);
                                cellIndex++;
                            }
                        }
                    }
                    map.put("max", max);
                    map.put("min", min);
                    map.put("size", size);
                    map = templeteLogicService.execExportMarkResultSimpleLogic(map);
                    if (max == size) {
                        break;
                    }
                    min = max;
                    max += SystemConstant.MAX_EXPORT_SIZE;
                    if (max >= size) {
                        max = size;
                    }
                }
                //临时缓冲区
                out = new ByteArrayOutputStream();
                wb.write(out);
                byte[] bookByteAry = out.toByteArray();
                inputStream = new ByteArrayInputStream(bookByteAry);
                StringBuilder stringBuilder = new StringBuilder(excelSj.toString());
                File finalFile = new File(stringBuilder.append(File.separator).append(missMarkResultStandardExportDtoList.get(0).getCourseName() + "_" + missMarkResultStandardExportDtoList.get(0).getCourseCode() + "_缺考考生").append(SystemConstant.EXCEL_PREFIX).toString());
                if (!finalFile.exists()) {
                    finalFile.getParentFile().mkdirs();
                    finalFile.createNewFile();
                }
                FileUtils.copyInputStreamToFile(inputStream, finalFile);
                files.add(finalFile);
            } catch (Exception e) {
                log.error("生成excel报错", e);
                e.printStackTrace();
            } finally {
                if (Objects.nonNull(wb)) {
                    wb.dispose();
                }
                if (Objects.nonNull(inputStream)) {
                    inputStream.close();
                }
                if (Objects.nonNull(out)) {
                    out.flush();
                    out.close();
                }
            }
        }
        map.put("finalSize", finalSize);
        map.put("line", line);
        return map;
    }
}