package com.qmth.teachcloud.report.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qmth.teachcloud.common.bean.auth.AuthBean;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.AssignEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.RoleTypeEnum;
import com.qmth.teachcloud.common.service.BasicCourseService;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.service.SysOrgService;
import com.qmth.teachcloud.common.util.ExcelUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.common.util.excel.ExcelError;
import com.qmth.teachcloud.report.business.bean.dto.ExamStudentTypeDto;
import com.qmth.teachcloud.report.business.bean.result.*;
import com.qmth.teachcloud.report.business.entity.*;
import com.qmth.teachcloud.report.business.enums.OrderEnum;
import com.qmth.teachcloud.report.business.enums.PublishStatusEnum;
import com.qmth.teachcloud.report.business.mapper.*;
import com.qmth.teachcloud.report.business.service.TAExamCourseRecordDioService;
import com.qmth.teachcloud.report.business.service.TBExamStudentService;
import com.qmth.teachcloud.report.business.utils.EncrypAES;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * <p>
 * 考生表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2021-06-01
 */
@Service
public class TBExamStudentServiceImpl extends ServiceImpl<TBExamStudentMapper, TBExamStudent> implements TBExamStudentService {

    @Resource
    TBExamStudentMapper tbExamStudentMapper;

    @Autowired
    BasicCourseService basicCourseService;

    @Resource
    TBStudentMapper tbStudentMapper;

    @Resource
    TAExamCourseRecordMapper taExamCourseRecordMapper;

    @Resource
    TBCommonRankLevelConfigMapper tbCommonRankLevelConfigMapper;

    @Resource
    TBPaperMapper tbPaperMapper;

    @Resource
    TAExamCourseRecordDioMapper taExamCourseRecordDioMapper;

    @Resource
    TAExamCourseRecordModMapper taExamCourseRecordModMapper;

    @Resource
    TBModuleConfigMapper tbModuleConfigMapper;

    @Resource
    TBModuleProficiencyMapper tbModuleProficiencyMapper;

    @Resource
    SysOrgService sysOrgService;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    TAExamCourseRecordDioService taExamCourseRecordDioService;

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

    /**
     * 查询开课学院列表
     *
     * @param schoolId
     * @param examId
     * @param courseCode
     * @param absent
     * @param current
     * @param status
     * @return
     */
    @Override
    public List<TBExamStudentResult> selectTeachCollegeList(Long schoolId, Long examId, String courseCode, Boolean absent, Boolean current, PublishStatusEnum status) {
        return tbExamStudentMapper.selectTeachCollegeList(schoolId, examId, courseCode, absent, current, Objects.nonNull(status) ? status.name() : null);
    }

    /**
     * 查询考查学院列表
     *
     * @param schoolId
     * @param examId
     * @param courseCode
     * @param absent
     * @param current
     * @param status
     * @return
     */
    @Override
    public List<TBExamStudentResult> selectInspectCollegeList(Long schoolId, Long examId, String courseCode, Boolean absent, Boolean current, PublishStatusEnum status) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        AuthBean authBean = commonCacheService.userAuthCache(sysUser.getId());
        if (Objects.nonNull(authBean) && Objects.nonNull(authBean.getRoleList()) && authBean.getRoleList().get(0).getType() == RoleTypeEnum.TEACHER) {
            List<Long> collegeIds = sysOrgService.findCollegeIds(sysUser.getOrgId());
            if (Objects.nonNull(collegeIds) && collegeIds.size() > 0) {
                return tbExamStudentMapper.selectInspectCollegeListByTeacher(schoolId, examId, courseCode, collegeIds, sysUser.getId(), absent, current, Objects.nonNull(status) ? status.name() : null);
            } else {
                return tbExamStudentMapper.selectInspectCollegeListByTeacher(schoolId, examId, courseCode, Objects.nonNull(sysUser.getOrgId()) ? Arrays.asList(sysUser.getOrgId()) : null, sysUser.getId(), absent, current, Objects.nonNull(status) ? status.name() : null);
            }
        }
        return tbExamStudentMapper.selectInspectCollegeList(schoolId, examId, courseCode, absent, current, Objects.nonNull(status) ? status.name() : null);
    }

    /**
     * 查询老师列表
     *
     * @param schoolId
     * @param examId
     * @param courseCode
     * @param inspectCollegeId
     * @param teachCollegeId
     * @param absent
     * @param current
     * @param status
     * @return
     */
    @Override
    public List<TBExamStudentResult> selectTeachList(Long schoolId, Long examId, String courseCode, Long inspectCollegeId, Long teachCollegeId, Boolean absent, Boolean current, PublishStatusEnum status) {
        return tbExamStudentMapper.selectTeachList(schoolId, examId, courseCode, inspectCollegeId, teachCollegeId, absent, current, Objects.nonNull(status) ? status.name() : null);
    }

    /**
     * 查询班级列表
     *
     * @param schoolId
     * @param examId
     * @param teacherId
     * @param courseCode
     * @param absent
     * @param current
     * @param status
     * @return
     */
    @Override
    public List<TBExamStudentResult> selectClassList(Long schoolId, Long examId, Long teacherId, String courseCode, Long inspectCollegeId, Boolean absent, Boolean current, PublishStatusEnum status) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        List<Long> orgIdList = new ArrayList<>();
        if (inspectCollegeId != null && inspectCollegeId > 0) {
            orgIdList.add(inspectCollegeId);
        } else {
            orgIdList = sysOrgService.findCollegeIds(sysUser.getOrgId());
        }
        return tbExamStudentMapper.selectClassList(schoolId, examId, teacherId, courseCode, orgIdList, absent, current, Objects.nonNull(status) ? status.name() : null);
    }

    @Override
    public IPage<TeachCollegeResult> listTeachCollegeResult(Long semesterId, Long examId, String courseCode, Boolean current, Long inspectCollegeId, Long teacherId, String studentParam, Integer pageNumber, Integer pageSize, String column, OrderEnum order) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long orgId = sysUser.getOrgId();
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<Long> collegeIds = sysOrgService.findCollegeIds(sysUser.getOrgId());
        IPage<TeachCollegeResult> listPage;
        if (Objects.nonNull(collegeIds) && collegeIds.size() > 0) {
            listPage = tbExamStudentMapper.listTeachCollegeResult(new Page<>(pageNumber, pageSize), schoolId, semesterId, examId, courseCode, current, inspectCollegeId, orgId, teacherId, studentParam, collegeIds, column, Objects.nonNull(order) ? order.name() : null);
        } else {
            listPage = tbExamStudentMapper.listTeachCollegeResult(new Page<>(pageNumber, pageSize), schoolId, semesterId, examId, courseCode, current, inspectCollegeId, orgId, teacherId, studentParam, Objects.nonNull(sysUser.getOrgId()) ? Arrays.asList(sysUser.getOrgId()) : null, column, Objects.nonNull(order) ? order.name() : null);
        }
        List<TeachCollegeResult> teachCollegeResultList = listPage.getRecords();
        for (TeachCollegeResult teachCollegeResult : teachCollegeResultList) {
            String code = teachCollegeResult.getStudentCode();
            teachCollegeResult.setStudentCodeEncoder(EncrypAES.encrypt(code));
        }
        return listPage;
    }

    @Override
    public void importFile(Long examId, MultipartFile file) throws IOException, NoSuchFieldException {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(ExamStudentTypeDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            // 只允许导入一个sheet
            if (finalExcelList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception("excel中只允许有一个sheet");
            }
            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> examTaskTempList = excelMap.get(i);
                for (int y = 0; y < examTaskTempList.size(); y++) {
                    ExamStudentTypeDto userImportDto = (ExamStudentTypeDto) examTaskTempList.get(y);
                    if (StringUtils.isBlank(userImportDto.getTicketNumber())) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[准考证号]必填"));
                    }
                    if (StringUtils.isBlank(userImportDto.getCourseCode())) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程代码]必填"));
                    }
                    if (StringUtils.isBlank(userImportDto.getCourseName())) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程名称]必填"));
                    }

                    // 课程是否存在并且与名称对应
                    QueryWrapper<BasicCourse> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, userImportDto.getCourseCode());
                    BasicCourse course = basicCourseService.getOne(queryWrapper);
                    if (course == null) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程代码]在系统中不存在"));
                    } else if (!course.getName().equals(userImportDto.getCourseName())) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程名称]与系统中不匹配"));
                    }
                }
            }
            if (excelErrorTemp.size() > 0) {
                List<String> errors = excelErrorTemp.stream().map(m -> m.getExcelErrorType()).collect(Collectors.toList());
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(errors));
            }
            return finalExcelList;
        });

        for (int i = 0; i < finalList.size(); i++) {
            LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
            List<Object> tempList = excelMap.get(i);
            for (int y = 0; y < tempList.size(); y++) {
                ExamStudentTypeDto examStudentTypeDto = (ExamStudentTypeDto) tempList.get(y);
                if (StringUtils.isNotBlank(examStudentTypeDto.getCurrent())) {
                    UpdateWrapper<TBExamStudent> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.lambda().set(TBExamStudent::getStudentCurrent, "应届".equals(examStudentTypeDto.getCurrent().trim()))
                            .eq(TBExamStudent::getExamId, examId)
                            .eq(TBExamStudent::getTicketNumber, examStudentTypeDto.getTicketNumber().trim())
                            .eq(TBExamStudent::getCourseCode, examStudentTypeDto.getCourseCode().trim());
                    this.update(updateWrapper);
                }
            }
        }
    }

    @Override
    public void exportTeachCollegeResult(Long semesterId, Long examId, String courseCode, Boolean current, Long inspectCollegeId, Long teacherId, String studentParam, String column, OrderEnum order) throws Exception {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        List<Long> collegeIds = sysOrgService.findCollegeIds(sysUser.getOrgId());
        List<TeachCollegeResult> list = null;
        if (Objects.nonNull(collegeIds) && collegeIds.size() > 0) {
            list = tbExamStudentMapper.listTeachCollegeResult(schoolId, semesterId, examId, courseCode, current, inspectCollegeId, teacherId, studentParam, collegeIds, column, Objects.nonNull(order) ? order.name() : null);
        } else {
            list = tbExamStudentMapper.listTeachCollegeResult(schoolId, semesterId, examId, courseCode, current, inspectCollegeId, teacherId, studentParam, Objects.nonNull(sysUser.getOrgId()) ? Arrays.asList(sysUser.getOrgId()) : null, column, Objects.nonNull(order) ? order.name() : null);
        }
        ExcelUtil.excelExport("开课成绩查询", TeachCollegeResult.class, list, ServletUtil.getResponse());
    }

    @Override
    public IPage<InspectCollegeResult> listInspectCollegeResult(Long semesterId, Long examId, String courseCode, Boolean current, Long inspectCollegeId, Long teacherId, Long clazzId, String studentParam, Integer pageNumber, Integer pageSize, String column, OrderEnum order) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        return tbExamStudentMapper.listInspectCollegeResult(new Page<>(pageNumber, pageSize), schoolId, semesterId, examId, courseCode, current, inspectCollegeId, teacherId, clazzId, studentParam, column, Objects.nonNull(order) ? order.name() : null);
    }

    @Override
    public void exportInspectCollegeResult(Long semesterId, Long examId, String courseCode, Boolean current, Long teachCollegeId, Long teacherId, Long clazzId, String studentParam, String column, OrderEnum order) throws Exception {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<InspectCollegeResult> list = tbExamStudentMapper.listInspectCollegeResult(schoolId, semesterId, examId, courseCode, current, teachCollegeId, teacherId, clazzId, studentParam, column, Objects.nonNull(order) ? order.name() : null);
        ExcelUtil.excelExport("考查成绩查询", InspectCollegeResult.class, list, ServletUtil.getResponse());
    }

    /**
     * 学生报告预览-列表接口
     *
     * @param iPage
     * @param schoolId
     * @param examId
     * @param collegeId
     * @param courseCode
     * @param clazzId
     * @param absent
     * @return
     */
    @Override
    public IPage<TBStudentReportResult> reportList(IPage<Map> iPage, Long schoolId, Long examId, Long collegeId, String courseCode, Long clazzId, Boolean absent, String studentCode) {
        if (schoolId == null) {
            schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        }
        IPage<TBStudentReportResult> page = tbExamStudentMapper.reportList(iPage, schoolId, examId, collegeId, courseCode, clazzId, absent, studentCode);
        List<TBStudentReportResult> tbStudentReportResultList = page.getRecords();
        for (TBStudentReportResult tbStudentReportResult : tbStudentReportResultList) {
            String code = tbStudentReportResult.getStudentCode();
            tbStudentReportResult.setStudentCodeEncoder(EncrypAES.encrypt(code));
        }
        return page;
    }

    /**
     * 学生报告-个人成绩总览接口
     *
     * @param schoolId
     * @param studentCode
     * @return
     */
    @Override
    public ReportResult reportResult(Long schoolId, String studentCode) {
        if (schoolId == null) {
            schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        }
        ReportResult reportResult = new ReportResult();
        // 考生信息
        StudentInfo studentInfo = tbStudentMapper.getStudentBySchoolIdAndStudentCode(schoolId, studentCode);
        if (Objects.isNull(studentInfo)) {
            studentInfo = new StudentInfo();
        }
        reportResult.setStudentInfo(studentInfo);

        //考试信息
        List<ExamInfo> examInfo = tbExamStudentMapper.listExamBySchoolIdAndStudentCode(schoolId, studentCode);
        if (Objects.isNull(examInfo) || examInfo.size() == 0) {
            examInfo = new ArrayList<>();
        } else {
            for (ExamInfo info : examInfo) {
                List<CourseInfo> courseInfos = tbExamStudentMapper.listCourseByExamIdAndStudentCode(schoolId, info.getExamId(), studentCode);
                info.setCourseInfo(courseInfos);
            }
        }
        reportResult.setExamInfo(examInfo);
        return reportResult;
    }

    @Override
    @Cacheable(value = SystemConstant.EXAM_STUDENT_REPORT, key = "#schoolId + '-' + #studentCode + '-' + #examId + '-' + #courseCode")
    public PersonalReportResult reportMark(Long schoolId, String studentCode, String examId, String courseCode) {
        if (schoolId == null) {
            schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        }
        PersonalReportResult personalReportResult = new PersonalReportResult();
        // 考生信息
        ExamStudentResult examStudentResult = buildExamStudentResult(schoolId, examId, studentCode, courseCode);
        if (Objects.isNull(examStudentResult)) {
            throw ExceptionResultEnum.ERROR.exception("未找到此考生信息");
        }
        personalReportResult.setStudent(examStudentResult);

        // 学院信息
        long s = System.currentTimeMillis();
        CollegeResult collegeResult = buildCollegeResult(schoolId, examId, studentCode, courseCode);
        if (Objects.isNull(collegeResult)) {
            throw ExceptionResultEnum.ERROR.exception("未找到考生的学院信息");
        }
        log.info("学院信息耗时 ： {}", System.currentTimeMillis() - s);
        personalReportResult.setCollege(collegeResult);
        return personalReportResult;
    }

    private CollegeResult buildCollegeResult(Long schoolId, String examId, String studentCode, String courseCode) {
        CollegeResult collegeResult = new CollegeResult();
        // 综合信息
        SynthesisResult synthesisResult = taExamCourseRecordMapper.getSynthesisResult(schoolId, examId, studentCode, courseCode);
        collegeResult.setSynthesis(synthesisResult);

        // 诊断信息
        DiagnosisResult diagnosisResult = new DiagnosisResult();

        QueryWrapper<TAExamCourseRecord> examCourseRecordQueryWrapper = new QueryWrapper<>();
        examCourseRecordQueryWrapper.lambda().eq(TAExamCourseRecord::getSchoolId, schoolId).eq(TAExamCourseRecord::getExamId, examId).eq(TAExamCourseRecord::getStudentCode, studentCode).eq(TAExamCourseRecord::getCourseCode, courseCode);
        long s1 = System.currentTimeMillis();
        List<TAExamCourseRecord> examCourseRecords = taExamCourseRecordMapper.selectList(examCourseRecordQueryWrapper);
        log.info("s1 查询耗时{}", System.currentTimeMillis() - s1);


        QueryWrapper<TBPaper> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, courseCode);
        long s2 = System.currentTimeMillis();
        List<TBPaper> papers = tbPaperMapper.selectList(queryWrapper);
        log.info("s2 查询耗时{}", System.currentTimeMillis() - s2);

        if (examCourseRecords.size() != 1) {
            throw ExceptionResultEnum.ERROR.exception("获取数据异常，应该有且仅有一条数据");
        }

        AssignEnum scoreType = papers.get(0).getScoreType();
        boolean isAssignedScore = false;
        if (!AssignEnum.NO_NEED_ASSIGN_SCORE.equals(scoreType)) {
            isAssignedScore = true;
        }
        diagnosisResult.setAssignedScore(isAssignedScore);
        double passScore = papers.get(0).getPassScore().doubleValue();
        boolean result = examCourseRecords.get(0).getAssignedScore().doubleValue() >= passScore;
        diagnosisResult.setResult(result);

        // 模块

        long s3 = System.currentTimeMillis();
        Set<String> moduleNames = taExamCourseRecordDioService.findDimensionTypesByCourseCode(schoolId, SystemConstant.convertIdToLong(examId), courseCode);
        log.info("s3查询耗时{}", System.currentTimeMillis() - s3);


        List<DiagnosisDetailResult> diagnosisDetailResults = new ArrayList<>();
        for (String moduleName : moduleNames) {
            DiagnosisDetailResult diagnosisDetailResult = new DiagnosisDetailResult();
            diagnosisDetailResult.setName(moduleName);
            QueryWrapper<TAExamCourseRecordMod> examCourseRecordModQueryWrapper = new QueryWrapper<>();
            examCourseRecordModQueryWrapper.lambda().eq(TAExamCourseRecordMod::getSchoolId, schoolId).eq(TAExamCourseRecordMod::getExamId, examId).eq(TAExamCourseRecordMod::getStudentCode, studentCode).eq(TAExamCourseRecordMod::getCourseCode, courseCode).eq(TAExamCourseRecordMod::getModuleType, moduleName);
            List<TAExamCourseRecordMod> examCourseRecordMods = taExamCourseRecordModMapper.selectList(examCourseRecordModQueryWrapper);
            if (examCourseRecordMods.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("获取数据异常，应该有且仅有一条数据");
            }
            TAExamCourseRecordMod taExamCourseRecordMod = examCourseRecordMods.get(0);
            String levelCode = taExamCourseRecordMod.getLevel();

            QueryWrapper<TBModuleConfig> moduleConfigQueryWrapper = new QueryWrapper<>();
            moduleConfigQueryWrapper.lambda().eq(TBModuleConfig::getExamId, examId).eq(TBModuleConfig::getCourseCode, courseCode).eq(TBModuleConfig::getLevelCode, levelCode).eq(TBModuleConfig::getModuleType, moduleName);
            List<TBModuleConfig> moduleConfigs = tbModuleConfigMapper.selectList(moduleConfigQueryWrapper);
            if (moduleConfigs.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("获取数据异常，应该有且仅有一条数据");
            }
            diagnosisDetailResult.setResult(moduleConfigs.get(0).getResult());
            diagnosisDetailResult.setAdvice(moduleConfigs.get(0).getAdvice());

            QueryWrapper<TBModuleProficiency> moduleProficiencyQueryWrapper = new QueryWrapper<>();
            moduleProficiencyQueryWrapper.lambda().eq(TBModuleProficiency::getExamId, examId).eq(TBModuleProficiency::getCourseCode, courseCode).eq(TBModuleProficiency::getModuleType, moduleName);
            List<TBModuleProficiency> moduleProficiencies = tbModuleProficiencyMapper.selectList(moduleProficiencyQueryWrapper);
            List<Map<String, String>> moduleProficiencieTemps = moduleProficiencies.stream().flatMap(e -> {
                Map<String, String> tbModuleProficiency = new HashMap();
                tbModuleProficiency.put("examId", e.getExamId().toString());
                tbModuleProficiency.put("courseCode", e.getCourseCode());
                tbModuleProficiency.put("moduleType", e.getModuleType());
                tbModuleProficiency.put("interpret", e.getInterpret());
                return Stream.of(tbModuleProficiency);
            }).distinct().collect(Collectors.toList());

            if (moduleProficiencieTemps.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("获取数据异常，应该有且仅有一条数据");
            }
            ModuleResult moduleResult = new ModuleResult();
            Map<String, String> tbModuleProficiency = moduleProficiencieTemps.get(0);
            String info = tbModuleProficiency.get("moduleType").concat(":").concat(tbModuleProficiency.get("interpret"));
            moduleResult.setInfo(info);

            long s4 = System.currentTimeMillis();
            List<ModuleDetailResult> dios = taExamCourseRecordDioMapper.listDiosBySchoolIdAndExamIdAndCourseCodeAndModuleName(schoolId, examId, courseCode, moduleName, studentCode);
            log.info("s4耗时{}", System.currentTimeMillis() - s4);

            moduleResult.setDios(dios);
            diagnosisDetailResult.setModules(moduleResult);

            DimensionResult dimensionResult = new DimensionResult();
            dimensionResult.setMyScore(taExamCourseRecordMod.getTotalScore().setScale(1, BigDecimal.ROUND_HALF_UP));
            dimensionResult.setMasteryRate(taExamCourseRecordMod.getScoreRate().multiply(new BigDecimal("100")).setScale(1, BigDecimal.ROUND_HALF_UP));
            dimensionResult.setDioFullScore(taExamCourseRecordMod.getFullScore().setScale(1, BigDecimal.ROUND_HALF_UP));

            long s5 = System.currentTimeMillis();
            List<DimensionDetailResult> subDios = taExamCourseRecordDioMapper.listSubDiosBySchoolIdAndExamIdAndStudentCodeAndCourseCodeAndModuleName(schoolId, examId, studentCode, courseCode, moduleName);
            log.info("s5耗时{}", System.currentTimeMillis() - s5);
            // 按二级维度code排序
            Collections.sort(subDios, new Comparator<DimensionDetailResult>() {
                @Override
                public int compare(DimensionDetailResult o1, DimensionDetailResult o2) {
                    String o1StringPart = o1.getCode().replaceAll("\\d", "");
                    String o2StringPart = o2.getCode().replaceAll("\\d", "");
                    if (o1StringPart.equalsIgnoreCase(o2StringPart)) {
                        return extractInt(o1.getCode()) - extractInt(o2.getCode());
                    }
                    return o1.getCode().compareTo(o2.getCode());
                }

                int extractInt(String s) {
                    String num = s.replaceAll("\\D", "");
                    return num.isEmpty() ? 0 : Integer.parseInt(num);
                }
            });

            dimensionResult.setSubDios(subDios);

            List<DimensionMasterysResult> dimensionMasterysResults = new ArrayList<>();
            List<String> defines = new ArrayList<>();
            for (TBModuleProficiency moduleProficiency : moduleProficiencies) {
                DimensionMasterysResult dimensionMasterysResult = new DimensionMasterysResult();
                dimensionMasterysResult.setLevel(moduleProficiency.getLevel());
                List<Double> grades = new ArrayList<>();
                grades.add(StringUtils.isNotBlank(moduleProficiency.getMin()) ? Double.valueOf(moduleProficiency.getMin()) : null);
                grades.add(StringUtils.isNotBlank(moduleProficiency.getMax()) ? Double.valueOf(moduleProficiency.getMax()) : null);
                dimensionMasterysResult.setGrade(grades);
                dimensionMasterysResults.add(dimensionMasterysResult);
                defines.add(moduleProficiency.getDefine());
            }
            dimensionResult.setDefine(defines);
            dimensionResult.setMasterys(dimensionMasterysResults);
            diagnosisDetailResult.setDetail(dimensionResult);
            diagnosisDetailResults.add(diagnosisDetailResult);
        }
        diagnosisResult.setList(diagnosisDetailResults);
        collegeResult.setDiagnosis(diagnosisResult);
        return collegeResult;
    }

    private ExamStudentResult buildExamStudentResult(Long schoolId, String examId, String studentCode, String courseCode) {
        ExamStudentResult examStudentResult = taExamCourseRecordMapper.getStudent(schoolId, examId, studentCode, courseCode);
        if (examStudentResult != null) {
            QueryWrapper<TBCommonRankLevelConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TBCommonRankLevelConfig::getExamId, examId).eq(TBCommonRankLevelConfig::getCourseCode, courseCode);
            List<TBCommonRankLevelConfig> commonRankLevelConfigs = tbCommonRankLevelConfigMapper.selectList(queryWrapper);
            List<LevelResult> levelResults = new ArrayList<>();
            for (TBCommonRankLevelConfig commonRankLevelConfig : commonRankLevelConfigs) {
                LevelResult levelResult = new LevelResult();
                levelResult.setLevel(commonRankLevelConfig.getLevel());
                List<Integer> grades = new ArrayList<>();
                grades.add(commonRankLevelConfig.getMin().intValue());
                grades.add(commonRankLevelConfig.getMax().intValue());
                levelResult.setGrade(grades);
                levelResults.add(levelResult);
            }
            examStudentResult.setLevels(levelResults);
        }
        return examStudentResult;
    }
}
