package com.qmth.teachcloud.common.sync;

import com.alibaba.fastjson.JSONObject;
import com.qmth.boot.tools.signature.SignatureType;
import com.qmth.teachcloud.common.SignatureEntityTest;
import com.qmth.teachcloud.common.bean.dto.stmms.*;
import com.qmth.teachcloud.common.bean.params.UserPushParam;
import com.qmth.teachcloud.common.bean.result.DBVerifyResult;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicSchool;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.SyncFileTypeEnum;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.util.HttpKit;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 同步云阅卷接口工具类
 * <p>
 * Date: 2021/10/29.
 */
@Component
public class CloudMarkingTaskUtils {
    private final static Logger log = LoggerFactory.getLogger(CloudMarkingTaskUtils.class);

    // 考试类型（逸教云默认是纸笔"SCAN_IMAGE"）
    private static final String SAVE_EXAM_TYPE = "SCAN_IMAGE";
    // 所有请求方法默认为"POST"
    private static final String POST_METHOD = "POST";

    // 默认分页数量
    private static final int defaultPageSize = 100;

    // 评卷员前缀
    private static final String MARKER_PREFIX = "M_";

    // 科组长前缀
    private static final String MARKER_LEADER_PREFIX = "S_";

    // 时间格式化
    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Resource
    private CommonCacheService commonCacheService;

    @Resource
    private DictionaryConfig dictionaryConfig;

    /**
     * 考试创建/更新接口
     *
     * @param code     唯一标识
     * @param name     考试名称
     * @param examTime 考试时间
     * @return 考试ID
     */
    public Long syncExam(Long schoolId, String code, String name, String examTime) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String examSaveUrl = dictionaryConfig.syncDataDomain().getExamSaveUrl();
        validUrl(hostUrl, examSaveUrl);
        String postUrl = hostUrl.concat(examSaveUrl);
        //参数
        Map<String, Object> map = new HashMap<>();
        map.put("code", validParam(code, null, true, "唯一标识"));
        map.put("name", validParam(name, null, true, "考试名称"));
        map.put("examTime", validParam(examTime, null, true, "考试时间"));
        map.put("type", SAVE_EXAM_TYPE);

        String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, examSaveUrl), map, null, null, null);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject.containsKey("id")) {
            return Long.valueOf(jsonObject.get("id").toString());
        } else {
            throw ExceptionResultEnum.ERROR.exception("考试同步失败");
        }
    }

    public boolean syncUser(UserPushParam userPushParam) throws IllegalAccessException {
        DBVerifyResult verifyResult = SystemConstant.verifyDBFields(userPushParam, userPushParam.getClass());
        if (!verifyResult.getStatus()) {
            throw ExceptionResultEnum.ERROR.exception(verifyResult.getMessage());
        }
        String account = userPushParam.getAccount();
        String name = userPushParam.getName();
        String password = userPushParam.getPassword();
        int roleValue = userPushParam.getRole().getValue();
        Boolean enable = userPushParam.getEnable();
        Long schoolId = userPushParam.getSchoolId();


        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String userSaveUrl = dictionaryConfig.syncDataDomain().getUserSaveUrl();
        String postUrl = hostUrl.concat(userSaveUrl);
        // 参数
        Map<String, Object> map = new HashMap<>();
        map.put("account", validParam(account, null, true, "关联名称（唯一标识）"));
        map.put("name", validParam(name, null, false, "名称"));
        map.put("password", validParam(password, null, false, "密码"));
        map.put("role", validParam(String.valueOf(roleValue), null, true, "类型：MARKER、SUBJECT_HEADER"));
        map.put("enable", validParam(enable, true, false, "是否启用"));
        try {
            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, userSaveUrl), map, null, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("updateTime")) {
                return true;
            } else {
                log.warn("用户推送（同步）失败");
                return false;
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            return false;
        }
    }

    /**
     * 考生创建/更新接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param examNumber  准考证号
     * @param studentCode 学号
     * @param name        姓名
     * @param college     学院
     * @param className   班级名称
     * @param teacher     教师姓名
     * @param subjectCode 科目代码
     * @param subjectName 科目名称
     * @param packageCode 签到表编号
     * @param paperType   试卷类型
     * @param examSite    考点
     * @param examRoom    考场
     */
    public boolean syncStudent(Long schoolId, String examId, String examNumber, String studentCode, String name, String college,
                               String className, String teacher, String subjectCode, String subjectName,
                               String packageCode, String paperType, String examSite, String examRoom) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String studentSaveUrl = dictionaryConfig.syncDataDomain().getStudentSaveUrl();
        validUrl(hostUrl, studentSaveUrl);
        String postUrl = hostUrl.concat(studentSaveUrl);
        try {
            //参数
            Map<String, Object> map = new HashMap<>();
            map.put("examId", validParam(examId, null, true, "考试ID"));
            map.put("examNumber", validParam(examNumber, null, true, "准考证号"));
            map.put("studentCode", validParam(studentCode, null, true, "学号"));
            map.put("name", validParam(name, null, true, "姓名"));
            map.put("college", validParam(college, "无", true, "学院"));
            map.put("className", validParam(className, null, true, "班级名称"));
            map.put("teacher", validParam(teacher, "无", true, "教师姓名"));
            map.put("subjectCode", validParam(subjectCode, null, true, "科目代码")); // 取试卷编号
            map.put("subjectName", validParam(subjectName, null, true, "科目名称"));
            map.put("packageCode", validParam(packageCode, "", false, "签到表编号"));
            map.put("paperType", validParam(paperType, "", false, "试卷类型"));
            map.put("examSite", validParam(examSite, "", false, "考点"));
            map.put("examRoom", validParam(examRoom, "", false, "考场"));

            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, studentSaveUrl), map, null, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("updateTime")) {
                return true;
            }
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
        return false;
    }


    /**
     * 文件公共上传接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     * @param type        文件类型  SyncFileTypeEnum枚举
     * @param file        文件
     */
    public String syncFile(Long schoolId, String examId, String subjectCode, SyncFileTypeEnum type, File file) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String fileUploadUrl = dictionaryConfig.syncDataDomain().getFileUploadUrl();
        validUrl(hostUrl, fileUploadUrl);
        fileUploadUrl = fileUploadUrl.replace("{type}", type.name().toLowerCase());
        String postUrl = hostUrl.concat(fileUploadUrl);
        try {
            Map<String, String> files = new HashMap<>();
            if (file.exists()) {
                files.put(file.getName(), file.getPath());
            }
            //表单数据
            Map<String, Object> formText = new HashMap<>();
            formText.put("examId", validParam(examId, null, true, "考试ID"));
            formText.put("subjectCode", validParam(subjectCode, null, true, "科目代码"));
            String fileName = file.getName();
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            if (type.equals(SyncFileTypeEnum.CARD)) {
                if (!"zip".equals(suffix) && !"json".equals(suffix)) {
                    throw ExceptionResultEnum.ERROR.exception("文件类型有误");
                }
            } else if (type.equals(SyncFileTypeEnum.PAPER) || type.equals(SyncFileTypeEnum.ANSWER)) {
                if (!"pdf".equals(suffix) && !"json".equals(suffix)) {
                    throw ExceptionResultEnum.ERROR.exception("文件类型有误");
                }
            } else {
                throw ExceptionResultEnum.ERROR.exception("请传入文件上传类型");
            }
            formText.put("format", suffix);
            formText.put("md5", DigestUtils.md5Hex(new FileInputStream(file)));

            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, fileUploadUrl), formText, files, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("success")) {
                String success = jsonObject.get("success").toString();
                if (Boolean.parseBoolean(success)) {
                    if (jsonObject.containsKey("url")) {
                        return jsonObject.get("url").toString();
                    } else {
                        return success;
                    }
                }
            }
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        } finally {
            if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                if (file != null && file.exists()) {
                    file.delete();
                }
            }
        }
        return "";
    }

    /**
     * 试卷结构创建/更新接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     * @param objective   是否客观题
     * @param paperType   试卷类型
     * @param questions   试卷结构JSON
     */
    public boolean syncPaperStructure(Long schoolId, String examId, String subjectCode, Boolean objective,
                                      String paperType, List<QuestionDTO> questions) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String structureUrl = dictionaryConfig.syncDataDomain().getStructureUrl();
        validUrl(hostUrl, structureUrl);
        String postUrl = hostUrl.concat(structureUrl);
        try {
            //参数
            PaperDTO paperDTO = new PaperDTO();
            paperDTO.setExamId(Integer.valueOf(validParam(examId, null, true, "考试ID")));
            paperDTO.setSubjectCode(validParam(subjectCode, null, true, "科目代码"));
            paperDTO.setObjective(validParam(objective, true, true, "是否客观题"));
            paperDTO.setPaperType(validParam(paperType, "#", false, "试卷类型"));
            paperDTO.setQuestions(validStructureParam(objective, questions));

            String jsonData = JSONObject.toJSONString(paperDTO);

            String result = HttpKit.sendPost(postUrl, jsonData, getHeaders(schoolId, structureUrl));
            JSONObject jsonObject = JSONObject.parseObject(result);
            return jsonObject.containsKey("updateTime");
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 试卷结构查询接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     * @param paperType   试卷编号
     */
    public List<Map> queryPaperStructure(Long schoolId, String examId, String subjectCode, String paperType) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String queryPaperStructure = dictionaryConfig.syncDataDomain().getQueryPaperStructure();
        validUrl(hostUrl, queryPaperStructure);
        String postUrl = hostUrl.concat(queryPaperStructure);
        try {
            //参数
            Map<String, String> map = new HashMap<>();
            map.put("examId", validParam(examId, null, true, "考试ID"));
            map.put("subjectCode", validParam(subjectCode, null, true, "科目代码")); // 取试卷编号
            map.put("paperType", validParam(paperType, "", false, "试卷类型"));

            String result = HttpKit.sendPost(postUrl, map, getHeaders(schoolId, queryPaperStructure));
            return JSONObject.parseArray(JSONObject.toJSON(result).toString(), Map.class);
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 创建评卷分组接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     * @param groups      试卷结构JSON
     */
    public boolean saveMarkerGroup(Long schoolId, String examId, String subjectCode, Integer trialCount, List<GroupDetailDTO> groups) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String groupSaveUrl = dictionaryConfig.syncDataDomain().getGroupSaveUrl();
        validUrl(hostUrl, groupSaveUrl);
        String postUrl = hostUrl.concat(groupSaveUrl);
        try {
            //参数
            GroupDTO groupDTO = new GroupDTO();
            groupDTO.setExamId(Integer.valueOf(validParam(examId, null, true, "考试ID")));
            groupDTO.setSubjectCode(validParam(subjectCode, null, true, "科目代码"));
            groupDTO.setTrialCount(Integer.valueOf(validParam(String.valueOf(trialCount), "0", true, "试评数量")));
            groupDTO.setGroups(validGroupParam(groups));

            String jsonData = JSONObject.toJSONString(groupDTO);

            String result = HttpKit.sendPost(postUrl, jsonData, getHeaders(schoolId, groupSaveUrl));
            JSONObject jsonObject = JSONObject.parseObject(result);
            return jsonObject.containsKey("updateTime");
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 分组数量查询接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     */
    public int countGroup(Long schoolId, String examId, String subjectCode) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String groupCountUrl = dictionaryConfig.syncDataDomain().getGroupCountUrl();
        validUrl(hostUrl, groupCountUrl);
        String postUrl = hostUrl.concat(groupCountUrl);
        try {
            //参数
            Map<String, Object> map = new HashMap<>();
            map.put("examId", validParam(examId, null, true, "考试ID"));
            map.put("subjectCode", validParam(subjectCode, null, true, "科目代码"));

            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, groupCountUrl), map, null, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("totalCount")) {
                return jsonObject.getIntValue("totalCount");
            }
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
        return 0;
    }

    /**
     * 分组数量查询接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     */
    public boolean deleteGroup(Long schoolId, String examId, String subjectCode) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String groupDeleteUrl = dictionaryConfig.syncDataDomain().getGroupDeleteUrl();
        validUrl(hostUrl, groupDeleteUrl);
        String postUrl = hostUrl.concat(groupDeleteUrl);
        try {
            //参数
            Map<String, Object> map = new HashMap<>();
            map.put("examId", validParam(examId, null, true, "考试ID"));
            map.put("subjectCode", validParam(subjectCode, null, true, "科目代码"));

            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, groupDeleteUrl), map, null, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            return jsonObject.containsKey("updateTime");
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 绑定评卷员接口
     *
     * @param schoolId    学校ID
     * @param examId      考试ID
     * @param subjectCode 科目代码
     * @param groupNumber 分组序号
     * @param loginName   用户名
     */
    public boolean saveMarker(Long schoolId, String examId, String subjectCode, Integer groupNumber, String loginName) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String markerSaveUrl = dictionaryConfig.syncDataDomain().getMarkerSaveUrl();
        validUrl(hostUrl, markerSaveUrl);
        String postUrl = hostUrl.concat(markerSaveUrl);
        try {
            //参数
            Map<String, Object> map = new HashMap<>();
            map.put("examId", validParam(examId, null, true, "考试ID"));
            map.put("subjectCode", validParam(subjectCode, null, true, "科目代码"));
            map.put("groupNumber", validParam(String.valueOf(groupNumber), null, true, "分组序号"));
            map.put("account", MARKER_PREFIX + validParam(loginName, null, true, "用户名"));

            String result = HttpKit.sendPost(postUrl, getHeaders(schoolId, markerSaveUrl), map, null, null, null);
            JSONObject jsonObject = JSONObject.parseObject(result);
            return jsonObject.containsKey("updateTime");
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 评卷员登录
     */
    public Map<String, Object> markLogin(SysUser sysUser) {
        String markLoginUrl = dictionaryConfig.syncDataDomain().getMarkLoginUrl();
        try {
            //参数
            return openLogin(sysUser, markLoginUrl, MARKER_PREFIX);
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 科组长登录
     */
    public Map<String, Object> markLeaderLogin(SysUser sysUser) {
        String markLeaderLoginUrl = dictionaryConfig.syncDataDomain().getMarkLeaderLoginUrl();
        try {
            //参数
            return openLogin(sysUser, markLeaderLoginUrl, MARKER_LEADER_PREFIX);
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 组装登录参数
     *
     * @param loginUrl 登录url
     * @param prefix   账号前缀
     */
    private Map<String, Object> openLogin(SysUser sysUser, String loginUrl, String prefix) {
        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        validUrl(hostUrl, loginUrl);
        String postUrl = hostUrl.concat(loginUrl);

        try {
            long time = System.currentTimeMillis();
            Map<String, Object> map = new HashMap<>();
            map.put("redirectUrl", postUrl);
            map.put("account", prefix + sysUser.getLoginName());
            map.put("name", sysUser.getLoginName());
            map.put("time", time);
            map.put("authorization", createSign(sysUser.getSchoolId(), time, loginUrl));
            return map;
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("登录信息获取失败");
        }
    }

    /**
     * http请求头
     *
     * @param url 请求URL
     */
    private Map<String, String> getHeaders(Long schoolId, String url) {
        long time = System.currentTimeMillis();
        Map<String, String> header = new HashMap<>();
        header.put(SystemConstant.HEADER_AUTHORIZATION, createSign(schoolId, time, url));
        header.put(SystemConstant.HEADER_TIME, String.valueOf(time));
        return header;
    }

    /**
     * 签名
     *
     * @param time 时间戳
     * @param url  请求URL
     */
    private String createSign(Long schoolId, long time, String url) {
        BasicSchool basicSchool = commonCacheService.schoolCache(schoolId);
        if (basicSchool == null) {
            throw ExceptionResultEnum.ERROR.exception("学校不存在");
        }
        if (!basicSchool.getEnable()) {
            throw ExceptionResultEnum.ERROR.exception("学校已禁用");
        }

        return SignatureEntityTest.build(SignatureType.SECRET, POST_METHOD, url, time, basicSchool.getAccessKey(), basicSchool.getAccessSecret());
    }

    /**
     * 校验参数值并返回（字符型）
     *
     * @param value        参数值
     * @param defaultValue 默认值
     * @param require      是否必填（true：是，false：否）
     * @param name         参数名称
     */
    private String validParam(String value, String defaultValue, boolean require, String name) {
        if (require && StringUtils.isAllBlank(value, defaultValue)) {
            throw ExceptionResultEnum.ERROR.exception((StringUtils.isBlank(name) ? "" : name) + "值必填");
        }
        return StringUtils.isBlank(value) ? defaultValue : value;

    }

    /**
     * 校验参数值并返回 （布尔型）
     *
     * @param value        参数值
     * @param defaultValue 默认值
     * @param require      是否必填
     * @param name         描述
     */
    private Boolean validParam(Boolean value, Boolean defaultValue, Boolean require, String name) {
        if (require && value == null && defaultValue == null) {
            throw ExceptionResultEnum.ERROR.exception((StringUtils.isBlank(name) ? "" : name) + "值必填");
        }
        return value == null ? defaultValue : value;

    }

    /**
     * 校验试卷结构值
     *
     * @param objective 是否客观题
     * @param questions 试卷结构JSON
     */
    private List<QuestionDTO> validStructureParam(Boolean objective, List<QuestionDTO> questions) {
        for (QuestionDTO question : questions) {
            validParam(String.valueOf(question.getMainNumber()), null, true, "大题号");
            validParam(question.getSubNumber(), null, true, "小题号");
            validParam(question.getMainTitle(), null, true, "大题名称");
            validParam(String.valueOf(question.getTotalScore()), null, true, "满分");
            if (objective) {
                validParam(question.getAnswer(), null, true, "标答");
            }
        }
        return questions;
    }

    /**
     * 校验分组参数
     *
     * @param groups 分组
     */
    private List<GroupDetailDTO> validGroupParam(List<GroupDetailDTO> groups) {
        for (GroupDetailDTO group : groups) {
            validParam(String.valueOf(group.getNumber()), null, true, "分组序号");
//            validParam(group.getPicList(), null, true, "小题号");
            validParam(String.valueOf(group.getDoubleRate()), "0", true, "双评比例");
            if (new BigDecimal(1).compareTo(BigDecimal.valueOf(group.getDoubleRate())) == 0) {
                validParam(String.valueOf(group.getArbitrateThreshold()), "0", true, "仲裁阈值");
                validParam(String.valueOf(group.getScorePolicy()), "AVG", true, "合分策略");
            }
            // 允许全零分、评卷模式非必填
            /*validParam(group.getEnableAllZero(), false, false, "允许全零分");
            validParam(group.getMarkMode(), "", false, "评卷模式");*/
            for (QuestionBaseDTO question : group.getQuestions()) {
                validParam(String.valueOf(question.getMainNumber()), null, true, "大题号");
                validParam(question.getSubNumber(), null, true, "小题号");
            }
        }
        return groups;
    }

    /**
     * 校验url是否配置
     *
     * @param urls URL数组
     */
    private void validUrl(String... urls) {
        if (StringUtils.isAnyBlank(urls)) {
            throw ExceptionResultEnum.ERROR.exception("云阅卷同步接口未正确配置");
        }
    }

    /**
     * 考试成绩考生数量查询接口
     *
     * @param schoolId
     * @param examId
     * @param examCode
     * @param examNumber
     * @param studentCode
     * @param subjectCode
     * @param college
     * @param className
     * @param teacher
     * @param withMarkTrack
     * @return
     */
    public int getStudentCount(Long schoolId, Integer examId, String examCode, String examNumber, String studentCode, String subjectCode, String college, String className, String teacher, boolean withMarkTrack) {
        Map<String, Object> map = new HashMap<>();
        map.put("examId", validParam(String.valueOf(examId), null, true, "考试ID"));
        map.put("withMarkTrack", validParam(withMarkTrack, true, false, "评分标记"));

        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String studentCountUrl = dictionaryConfig.syncDataDomain().getStudentCountUrl();
        validUrl(hostUrl, studentCountUrl);
        String postUrl = hostUrl.concat(studentCountUrl);

        //请求
        String res;
        try {
            res = HttpKit.sendPost(postUrl, getHeaders(schoolId, studentCountUrl), map, null, null, null);
        } catch (Exception e) {
            log.info("云阅卷：调用考试成绩考生数量查询接口请求异常，{}", e.getMessage());
            throw new RuntimeException("云阅卷：调用考试成绩考生数量查询接口请求异常，" + e.getMessage());
        }
        if (Objects.isNull(res)) {
            log.info("云阅卷：调用考试成绩考生数量查询接口返回值为null");
            throw new RuntimeException("云阅卷：调用考试成绩考生数量查询接口返回值为null");
        }
        JSONObject object = JSONObject.parseObject(res);
        return Integer.parseInt(object.get("totalCount").toString());
    }

    /**
     * 考试成绩考生查询接口
     *
     * @param schoolId
     * @param examId
     * @param examCode
     * @param examNumber
     * @param studentCode
     * @param subjectCode
     * @param college
     * @param className
     * @param teacher
     * @param withMarkTrack
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<Map> getStudentScore(Long schoolId, Integer examId, String examCode, String examNumber, String studentCode, String subjectCode, String college, String className, String teacher, boolean withMarkTrack, int pageNo, int pageSize) {
        Map<String, Object> map = new HashMap<>();
        map.put("examId", validParam(String.valueOf(examId), null, true, "考试ID"));
        map.put("withMarkTrack", validParam(withMarkTrack, true, false, "评分标记"));
        map.put("pageNumber", validParam(String.valueOf(pageNo), null, true, "页码"));
        map.put("pageSize", validParam(String.valueOf(pageSize), null, true, "数量"));

        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
        String studentScoreUrl = dictionaryConfig.syncDataDomain().getStudentScoreUrl();
        validUrl(hostUrl, studentScoreUrl);
        String postUrl = hostUrl.concat(studentScoreUrl);
        //请求
        String res;
        try {
            res = HttpKit.sendPost(postUrl, getHeaders(schoolId, studentScoreUrl), map, null, null, null);
        } catch (Exception e) {
            log.info("云阅卷：调用考试成绩考生查询接口请求异常，{}", e.getMessage());
            throw new RuntimeException("云阅卷：调用考试成绩考生查询接口请求异常，" + e.getMessage());
        }
        if (Objects.isNull(res)) {
            log.info("云阅卷：调用考试成绩考生查询接口返回值为null");
            throw new RuntimeException("云阅卷：调用考试成绩考生查询接口返回值为null");
        }
        return JSONObject.parseArray(JSONObject.toJSON(res).toString(), Map.class);
    }

    public int getDefaultPageSize() {
        return defaultPageSize;
    }
}
