package com.qmth.jkserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.core.kw.IKwTempDataProcessor;
import com.qmth.jkserver.core.kw.KwTempDataFactory;
import com.qmth.jkserver.dao.*;
import com.qmth.jkserver.dto.ExamPlanDto;
import com.qmth.jkserver.dto.ExamStudentDto;
import com.qmth.jkserver.dto.KWObjectDto;
import com.qmth.jkserver.enums.*;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.service.*;
import com.qmth.jkserver.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 考试计划
 *
 * @author tianjun
 */
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class JkExamPlanServiceImpl extends ServiceImpl<ExamPlanDao, ExamPlan> implements JkExamPlanService {

    private static final Logger LOGGER = LoggerFactory.getLogger(JkExamPlanServiceImpl.class);

    @Resource
    private ExamPlanDao examPlanDao;

    @Resource
    private ExamRoomTempDao examRoomTempDao;

    @Resource
    private ExamStudentTempDao examStudentTempDao;

    @Resource
    private ExamStageTempDao examStageTempDao;

    @Resource
    private ExamPaperTempDao examPaperTempDao;

    @Resource
    private ExamCodeDao examCodeDao;

    @Resource
    private AttachmentDao attachmentDao;

    @Resource
    private ExamStageDao examStageDao;

    @Resource
    @Lazy
    private KWService kwService;

    @Resource
    @Lazy
    ExamPaperTempService examPaperTempService;

    @Resource
    @Lazy
    JkExamPlanService examPlanService;

    @Resource
    JkExamCodeService jkExamCodeService;

    @Resource
    JkPaperUncoilingService jkPaperUncoilingService;

    @Resource
    JkExamStudentTempService jkExamStudentTempService;

    @Resource
    JkExamRoomTempService jkExamRoomTempService;

    @Resource
    JkExamRoomAddressTempService jkExamRoomAddressTempService;

    @Resource
    JkExamStageTempService jkExamStageTempService;

    @Resource
    JkExamStageService jkExamStageService;

    @Resource
    JkExamStudentAdditionalTempService jkExamStudentAdditionalTempService;

    @Resource
    ExamStudentDao examStudentDao;

    @Resource
    ExamStudentAnswerService examStudentAnswerService;

    @Resource
    JkExamRoomService jkExamRoomService;

    /**
     * 删除paperTemp
     *
     * @param examCode
     */
    @Override
    public void deleteKwCoursePaperTemp(String examCode) {
//        mongoTemplate.remove(new Query().addCriteria(Criteria.where("examCode").is(examCode)), ExamPaperTemp.class);
        QueryWrapper<ExamPaperTemp> examPaperTempQueryWrapper = new QueryWrapper<>();
        examPaperTempQueryWrapper.lambda().eq(ExamPaperTemp::getExamCode, examCode);
        examPaperTempService.remove(examPaperTempQueryWrapper);
    }

    //新增
    @Override
    public ExamPlan save(ExamPlanDto examPlanDto) throws Exception {
        Long schoolId = (Long) ServletUtil.getRequestHeaderSchoolId();
        if (StringUtils.isEmpty(examPlanDto.getExamCode())) {
            throw new JkServerException(JkServerException.EXAM_CODE_IS_NULL.getCode(), "考试识别码不能够为null值");
        }
        List<ExamCode> examCodes = examCodeDao.findByExamCode(examPlanDto.getExamCode());
        if (examCodes.size() == 0) {
            throw new JkServerException(JkServerException.EXAM_CODE_INVALID.getCode(), "考试识别码在系统中不存在");
        }
        ExamCode examCode = examCodes.get(0);
        if (examCode.getUsed() && examCodeDao.findByExamCode(examPlanDto.getExamCode()) != null) {
            throw new JkServerException(JkServerException.EXAM_CODE_INVALID.getCode(), "考试识别码已经被占用");
        }
        List<ExamPlan> examPlans = examPlanDao.findByExamCode(examPlanDto.getExamCode());
        if (examPlans.size() > 0) {
            throw new JkServerException(JkServerException.EXAM_CODE_INVALID.getCode(), "考试识别码已经被占用");
        }
        List<ExamPlan> checkNames = examPlanDao.findByName(examPlanDto.getName());
        if (checkNames.size() > 0) {
            throw new JkServerException(JkServerException.EXAM_PLAN_NAME_ALREADY_EXISTS.getCode(), "考试计划名称已经存在");
        }
        if (examPlanDto.getCreator() == null) {
            throw JkServerException.withFieldValidateError("必须指定任务创建者");
        }
        ExamPlan examPlan = new ExamPlan();
        examPlan.setId(SystemConstant.getDbUuid());
        examPlan.setEnable(true);
        examPlan.setExamStatus(ExamStatus.UN_PUBLISHED);
        examPlan.setExamType(examPlanDto.getExamType());
        examPlan.setName(examPlanDto.getName());
        examPlan.setExamCode(examPlanDto.getExamCode());
        examPlan.setCreatorId(examPlanDto.getCreator().getId());
        examPlan.setSimulation(examPlanDto.getSimulation() != null ? examPlanDto.getSimulation() : "0");
        examPlan.setPaperRule(examPlanDto.getPaperRule());
        examPlan.setLoginRule(examPlanDto.getLoginRule());
        examPlan.setClientTheme(examPlanDto.getClientTheme());
        examPlan.setCreateTime(System.currentTimeMillis());
        examPlan.setEnable(true);
//        examPlan.setFaceVerify(examPlanDto.getFaceVerify());
        examPlan.setFaceVerifyOpen(examPlanDto.getFaceVerify().getOpen());
        examPlan.setFaceVerifyIntervalTime(examPlanDto.getFaceVerify().getIntervalTime());
        examPlan.setOpenMonitor(examPlanDto.getOpenMonitor());
        examPlan.setSceneScore(examPlanDto.getSceneScore() == null ? SceneScore.NO : examPlanDto.getSceneScore());
        this.addExamData(examPlan, examPlanDto);
        Assert.notNull(examPlan.getExamCode(), "考试识别码不能够为空");
        Assert.notNull(examPlan.getExamType(), "考试类型不能够为空");
        Assert.notNull(examPlan.getExamStatus(), "考试状态不能够为空");
        Assert.notNull(examPlan.getStartTime(), "考试开始时间不能够为空");
        Assert.notNull(examPlan.getEndTime(), "考试结束时间不能够为空");
        examPlan.setSchoolId(schoolId);
        examPlanService.saveOrUpdate(examPlan);
        examCode.setUsed(true);
        jkExamCodeService.saveOrUpdate(examCode);
        return examPlan;
    }

    protected boolean isAlreadyExists(String examCode) {
        if (StringUtils.isEmpty(examCode)) {
            throw new JkServerException("考试识别码为空");
        }
        return examCodeDao.findByExamCode(examCode).size() > 0;
    }

    @Override
    public ExamPlan update(ExamPlanDto examPlanDto) throws Exception {
        //判断当前考试计划是否可以编辑
        ExamPlan old = this.findById(examPlanDto.getId());
        if (old == null) {
            throw new JkServerException("ID不存在:" + examPlanDto.getId());
        }
        if (ExamStatus.PUBLISHED.equals(old.getExamStatus())) {
            throw new JkServerException("考试任务已经发布，不允许编辑");
        }
        if (old.getStartTime().compareTo(System.currentTimeMillis()) < 0) {
            throw new JkServerException("已经过了考试任务的开始时间,不允许编辑");
        }
        List<ExamPlan> checkNames = examPlanDao.findByName(examPlanDto.getName());
        if (checkNames.size() > 0 && !checkNames.get(0).getId().equals(old.getId())) {
            throw new JkServerException(JkServerException.EXAM_PLAN_NAME_ALREADY_EXISTS.getCode(), "考试计划名称已经存在");
        }
        boolean canEdit = canEdit(examPlanDto.getExamCode());
        if (!canEdit) {
            throw new JkServerException("当前考试计划下已经上传了考生答案数据，故不允许编辑");
        }
        old.setName(examPlanDto.getName());
        old.setExamType(examPlanDto.getExamType());
        old.setSimulation(examPlanDto.getSimulation() != null ? examPlanDto.getSimulation() : "0");
        old.setPaperRule(examPlanDto.getPaperRule());
        old.setLoginRule(examPlanDto.getLoginRule());
        old.setClientTheme(examPlanDto.getClientTheme());
        old.setOpenMonitor(examPlanDto.getOpenMonitor());
        old.setSceneScore(examPlanDto.getSceneScore() == null ? SceneScore.NO : examPlanDto.getSceneScore());
//        old.setFaceVerify(examPlanDto.getFaceVerify());
        old.setFaceVerifyOpen(examPlanDto.getFaceVerify().getOpen());
        old.setFaceVerifyIntervalTime(examPlanDto.getFaceVerify().getIntervalTime());
        if (!old.getExamType().equals(examPlanDto.getExamType())) {
            this.addExamData(old, examPlanDto);
        } else {
            KwFile kwFile = kwService.findKwFileByExamCode(old.getExamCode());
            if (kwFile == null) {
                throw new JkServerException("无法获取到当前考试任务的已存储文件对象.");
            }
            //如果某一个文件的参数没有传递  则直接使用该文件上次校验成功的临时文件来校验当前新上传的文件数据,这个逻辑在页面回填的时候已经控制
            if (ExamType.UTEST.equals(old.getExamType()) &&
                    Objects.isNull(examPlanDto.getAdditionalFileId())) {
                examPlanDto.setAdditionalFileId(kwFile.getStudentAdditionalFileTempId());
            }
            this.addExamData(old, examPlanDto);
            //判断编辑前后的试卷文件是否变更,如果有变更则清除当前考试任务已经设置的开卷密码
            if (kwFile.getPaperFileTempId() != null && Objects.nonNull(examPlanDto.getPaperFileId())) {
                Attachment attachment = attachmentDao.findById(examPlanDto.getPaperFileId());
                if (attachment != null) {
                    Attachment attachmentTemp = attachmentDao.findById(kwFile.getPaperFileTempId());
//                    String oldmd5 = kwFile.getPaperFileTemp().getMd5();
                    String oldmd5 = attachmentTemp.getMd5();
                    if (!attachment.getMd5().equalsIgnoreCase(oldmd5)) {
//                        Query rmQuery = new Query();
//                        rmQuery.addCriteria(Criteria.where("examCode").is(kwFile.getExamCode()));
//                        mongoTemplate.remove(rmQuery, ExamPaperUncoiling.class);
                        QueryWrapper<ExamPaperUncoiling> examPaperUncoilingQueryWrapper = new QueryWrapper<>();
                        examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getExamCode, kwFile.getExamCode());
                        jkPaperUncoilingService.remove(examPaperUncoilingQueryWrapper);
                    }
                }
            }
        }
        examPlanService.saveOrUpdate(old);
        return old;
    }

    @Override
    public void deleteById(Long id) {
        ExamPlan ex = examPlanDao.findById(id);
        ex.setEnable(false);
        examPlanService.saveOrUpdate(ex);
    }

    @Override
    public ExamPlan findById(Long id) {
        return examPlanDao.findById(id);
    }

    @Override
    public Page<ExamPlan> findAll(ExamPlanDto searchCondition, int curPage, int pageSize) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("enable").is(true));
        QueryWrapper<ExamPlan> examPlanQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(searchCondition.getName())) {
//            query.addCriteria(Criteria.where("name").regex(searchCondition.getName()));
            examPlanQueryWrapper.lambda().like(ExamPlan::getName, searchCondition.getName());
        }
        if (searchCondition.getExamType() != null) {
//            query.addCriteria(Criteria.where("examType").is(searchCondition.getExamType()));
            examPlanQueryWrapper.lambda().eq(ExamPlan::getExamType, searchCondition.getExamType());
        }
        if (searchCondition.getExamStatus() != null) {
//            query.addCriteria(Criteria.where("examStatus").is(searchCondition.getExamStatus()));
            examPlanQueryWrapper.lambda().eq(ExamPlan::getExamStatus, searchCondition.getExamStatus());
        }
        if (searchCondition.getStartTime() != null) {
//            query.addCriteria(Criteria.where("startTime").gte(searchCondition.getStartTime()));
            examPlanQueryWrapper.lambda().ge(ExamPlan::getStartTime, searchCondition.getStartTime());
        }
        if (searchCondition.getEndTime() != null) {
//            query.addCriteria(Criteria.where("endTime").lte(searchCondition.getEndTime()));
            examPlanQueryWrapper.lambda().le(ExamPlan::getEndTime, searchCondition.getEndTime());
        }
//        if (searchCondition.getCreator() != null && !searchCondition.getCreator().getUserName().equals("super")) {
////            query.addCriteria(Criteria.where("creatorId").is(searchCondition.getCreator().getId()));
//            examPlanQueryWrapper.lambda().eq(ExamPlan::getCreatorId, searchCondition.getCreator().getId());
//        }
        if (Objects.nonNull(searchCondition.getSchoolId()) && searchCondition.getSchoolId().longValue() > 0) {
            examPlanQueryWrapper.lambda().eq(ExamPlan::getSchoolId, searchCondition.getSchoolId());
        }
//        examPlanQueryWrapper.lambda().orderByDesc(ExamPlan::getCreateTime);
//        query.with(new Sort(Direction.DESC, "createTime"));
//        long count = this.mongoTemplate.count(query, ExamPlan.class);
//        long count = examPlanService.count(examPlanQueryWrapper);
//        query.limit(pageSize);
//        query.skip((curPage - 1) * pageSize);
//        List<ExamPlan> examPlanList = this.mongoTemplate.find(query, ExamPlan.class);
//        List<ExamPlan> examPlanList = examPlanService.list(examPlanQueryWrapper);
        IPage<ExamPlan> examPlanIPage = examPlanDao.findByNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(curPage, pageSize),
                searchCondition.getName(), Objects.nonNull(searchCondition.getExamType()) ? searchCondition.getExamType().name() : null, Objects.nonNull(searchCondition.getExamStatus()) ? searchCondition.getExamStatus().name() : null,
                searchCondition.getStartTime(), searchCondition.getEndTime(), Objects.nonNull(searchCondition.getSchoolId()) && searchCondition.getSchoolId().longValue() > 0 ? searchCondition.getSchoolId() : null);
        return new PageImpl<ExamPlan>(examPlanIPage.getRecords(), PageRequest.of(curPage - 1, pageSize), examPlanIPage.getTotal());
    }

    /**
     * 查询所有考试任务
     *
     * @return
     */
    @Override
    public List<ExamPlan> findExamPlanAllByTask() {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examType").is(ExamType.NORMAL.name()));
//        query.addCriteria(Criteria.where("examStatus").is(ExamStatus.PUBLISHED.name()));
//        query.addCriteria(Criteria.where("enable").is(true));
//        query.with(new Sort(Sort.Direction.DESC, "createTime"));
//        return mongoTemplate.find(query, ExamPlan.class);
        QueryWrapper<ExamPlan> examPlanQueryWrapper = new QueryWrapper<>();
        examPlanQueryWrapper.lambda().eq(ExamPlan::getExamType, ExamType.NORMAL)
                .eq(ExamPlan::getExamStatus, ExamStatus.PUBLISHED)
                .eq(ExamPlan::getEnable, true)
                .orderByDesc(ExamPlan::getCreateTime);
        return examPlanService.list(examPlanQueryWrapper);
    }

    @Override
    public ExamPlan updatExamStatus(String id, ExamStatus status) {
        ExamPlan ex = examPlanDao.findById(Long.parseLong(id));
        ex.setExamStatus(status);
        examPlanService.saveOrUpdate(ex);
        return ex;
    }

    @Override
    public ExamPlan findByExamCode(String examCode) {
        List<ExamPlan> examPlans = examPlanDao.findByExamCode(examCode);
        return examPlans.size() > 0 ? examPlans.get(0) : null;
    }

    @Override
    public List<ExamStudentTemp> findKwStudentTemp(String examCode, Long attachmentId, int skip, int
            limit) {
//        DBObject dbObject = new BasicDBObject();
//        dbObject.put("exam_code", examCode);
//        dbObject.put("attachment_id", attachmentId);
        long time1 = System.currentTimeMillis();
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_student_temp").find(dbObject).skip(skip).limit(limit);
        long time2 = System.currentTimeMillis();
//        LOGGER.info("------------query student temp data use " + ((time2 - time1) / 1000) + "(s)----------------------------");
//        List<DBObject> list = new ArrayList<DBObject>();
//        while (dbCursor.hasNext()) {
//            DBObject res = dbCursor.next();
//            list.add(res);
//        }
//        dbCursor.close();
        QueryWrapper<ExamStudentTemp> examStudentTempQueryWrapper = new QueryWrapper<>();
        examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getExamCode, examCode)
                .eq(ExamStudentTemp::getAttachmentId, attachmentId);
        examStudentTempQueryWrapper.last(" limit " + limit);
        List<ExamStudentTemp> list = jkExamStudentTempService.list(examStudentTempQueryWrapper);
        long time3 = System.currentTimeMillis();
        LOGGER.info("--------------end convert ExamStudentTemp use time:" + ((time3 - time2) / 1000) + "(s)-------------------------");
        return list.subList(skip, list.size());
//		Query query = new Query();
//		query.addCriteria(Criteria.where("examCode").is(examCode));
//		query.addCriteria(Criteria.where("attachmentId").is(attachmentId));
//		long time1 = System.currentTimeMillis();
//		query.skip(skip);
//		query.limit(limit);
//		List<ExamStudentTemp> examStudentTemps = mongoTemplate.find(query, ExamStudentTemp.class);
//		long time2 = System.currentTimeMillis();
//		LOGGER.info("------------query student temp data use " + ((time2 - time1) / 1000) + "(s)----------------------------");
//		return examStudentTemps;
    }

    private static Date parseDate(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
            return sdf.parse(date);
        } catch (ParseException e) {
            LOGGER.error("parseDate Error:", e);
            throw JkServerException.withMessage("parse date error,date:" + date);
        }
    }

//    private String getString(DBObject dbObject, String key) {
//        if (dbObject.get(key) == null) {
//            return null;
//        } else {
//            return dbObject.get(key).toString();
//        }
//    }

    @Override
    public List<ExamRoomTemp> findKwRoomsTemp(String examCode, Long attachmentId) {
        return examRoomTempDao.findByExamCodeAndAttachmentId(examCode, attachmentId);
    }

    @Override
    public List<ExamStudentTemp> saveKwStudentTemp(List<ExamStudentTemp> temps) {
        if (temps != null && temps.size() > 0) {
            jkExamStudentTempService.saveOrUpdateBatch(temps);
            return temps;
        }
        return null;
    }

    @Override
    public List<ExamRoomTemp> saveKwRoomTemp(List<ExamRoomTemp> temps) {
        if (temps != null && temps.size() > 0) {
            jkExamRoomTempService.saveOrUpdateBatch(temps);
            return temps;
        }
        return null;
    }

    @Override
    public List<ExamRoomAddressTemp> saveKwRoomAddressTemp(List<ExamRoomAddressTemp> temps) {
        if (temps != null && temps.size() > 0) {
            jkExamRoomAddressTempService.saveOrUpdateBatch(temps);
            return temps;
        }
        return null;
    }

    @Override
    public List<ExamStageTemp> saveKwStageTemp(List<ExamStageTemp> temps) {
        if (temps != null && temps.size() > 0) {
            jkExamStageTempService.saveOrUpdateBatch(temps);
            return temps;
        }
        return null;
    }

    @Override
    public List<ExamStageTemp> findKwStageTemps(String examCode, Long attachmentId) {
        return examStageTempDao.findByExamCodeAndAttachmentId(examCode, attachmentId);
    }

    @Override
    public List<ExamPaperTemp> findKwCoursePaperTemp(String examCode, Long attachmentId) {
        return examPaperTempDao.findByExamCodeAndAttachmentId(examCode, attachmentId);
    }


    private String makeExamCode() {
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
        StringBuilder sb = new StringBuilder(4);
        for (int i = 0; i < 4; i++) {
            char ch = str.charAt(new Random().nextInt(str.length()));
            sb.append(ch);
        }
        return sb.toString();
    }

    private void addExamData(ExamPlan examPlan, ExamPlanDto examPlanDto) throws Exception {
        IKwTempDataProcessor kwValidate = KwTempDataFactory.getInsatance(examPlanDto.getExamType());
        KWObjectDto kwObject = kwValidate.execute(examPlanDto.getExamCode(), examPlanDto.getExamType(), examPlanDto.getKcFileId(),
                examPlanDto.getKwZipFileId(), examPlanDto.getPaperFileId(), examPlanDto.getAdditionalFileId(), examPlanDto.getSceneScoreFileId());
        kwService.saveKwObejct(kwObject);
        //设置该考试任务的 最早开始时间 以及  最晚结束时间
        Long startTime = getExamPlanStartTime(examPlan.getExamCode());
        Long endTime = getExamPlanEndTime(examPlan.getExamCode());
        examPlan.setStartTime(startTime);
        examPlan.setEndTime(endTime);
        //存储考情监控信息
        if (examPlanDto.getOpenMonitor() != null && examPlanDto.getOpenMonitor().equals(OpenMonitor.YES)) {
            if (Objects.isNull(examPlanDto.getRoomMonitorFileId())) {
                throw JkServerException.withFieldValidateError("如果开启了考情监控，请上传考情监控数据包");
            } else {
                kwService.saveRoomMonitorInfo(examPlan.getExamCode(), String.valueOf(examPlanDto.getRoomMonitorFileId()));
            }
        }
        //是否开启现场出分
        if (examPlanDto.getSceneScore() != null && examPlanDto.getSceneScore().equals(SceneScore.YES)) {
            if (Objects.isNull(examPlanDto.getSceneScoreFileId())) {
                throw JkServerException.withFieldValidateError("如果开启了现场出分，请上传标答以及评分规则文件");
            }
        }
    }

    @Override
    public List<ExamPaperTemp> saveKwCoursePaperTemp(List<ExamPaperTemp> examPaperTemps) {
        examPaperTempService.saveOrUpdateBatch(examPaperTemps);
        return examPaperTemps;
    }

    @Override
    public List<ExamStudentAdditionalTemp> saveKwstudentAdditionalTemp(List<ExamStudentAdditionalTemp> temps) {
        if (temps != null && temps.size() > 0) {
            jkExamStudentAdditionalTempService.saveOrUpdateBatch(temps);
            return temps;
        }
        return null;
    }

    @Override
    public List<ExamStudentAdditionalTemp> findKwStudentAdditionalTemp(String examCode, Long attachmentId, int skip, int
            limit) {
//        DBObject dbObject = new BasicDBObject();
//        dbObject.put("exam_code", examCode);
//        dbObject.put("attachment_id", attachmentId);
        long time1 = System.currentTimeMillis();
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_student_additional_temp").find(dbObject).skip(skip).limit(limit);
        long time2 = System.currentTimeMillis();
//        LOGGER.info("--------------end query ExamStudentAdditionalTemp use time:" + ((time2 - time1) / 1000) + "(s)-------------------------");
//        List<DBObject> list = new ArrayList<DBObject>();
//        while (dbCursor.hasNext()) {
//            DBObject document = dbCursor.next();
//            list.add(document);
//        }
//        dbCursor.close();
        QueryWrapper<ExamStudentAdditionalTemp> examStudentAdditionalTempQueryWrapper = new QueryWrapper<>();
        examStudentAdditionalTempQueryWrapper.lambda().eq(ExamStudentAdditionalTemp::getExamCode, examCode)
                .eq(ExamStudentAdditionalTemp::getStudentId, attachmentId);
        examStudentAdditionalTempQueryWrapper.last(" limit " + limit);
        List<ExamStudentAdditionalTemp> list = jkExamStudentAdditionalTempService.list(examStudentAdditionalTempQueryWrapper);
        long time3 = System.currentTimeMillis();
        LOGGER.info("--------------end convert ExamStudentAdditionalTemp use time:" + ((time3 - time2) / 1000) + "(s)-------------------------");
        return list.subList(skip, list.size());
//		Query query = new Query();
//		query.addCriteria(Criteria.where("examCode").is(examCode));
//		query.addCriteria(Criteria.where("attachmentId").is(attachmentId));
//		query.skip(skip);
//		query.limit(limit);
//		LOGGER.info("--------------start query ExamStudentAdditionalTemp-------------------------");
//		long time1 = System.currentTimeMillis();
//		List<ExamStudentAdditionalTemp> list= mongoTemplate.find(query, ExamStudentAdditionalTemp.class);
//		long time2 = System.currentTimeMillis();
//		LOGGER.info("--------------end query ExamStudentAdditionalTemp use time:"+((time2-time1)/1000)+"(s)-------------------------");
//		return list;
    }


    //返回考试任务的最早开始时间  只是 获取日期
    @Override
    public Long getExamPlanStartTime(String examCode) throws ParseException {
//        Query queryStartTime = new Query();
//        Criteria.where("examCode").equals(examCode);
//        queryStartTime.addCriteria(Criteria.where("examCode").is(examCode));
//        queryStartTime.with(new Sort(Direction.ASC, "batchStartTime"));
//        List<ExamStage> examStages = mongoTemplate.find(queryStartTime, ExamStage.class);
//        Date datetime = examStages.size() > 0 ? examStages.get(0).getBatchStartTime() : null;
        QueryWrapper<ExamStage> examStageQueryWrapper = new QueryWrapper<>();
        examStageQueryWrapper.lambda().eq(ExamStage::getExamCode, examCode)
                .orderByDesc(ExamStage::getBatchStartTime);
        List<ExamStage> examStages = jkExamStageService.list(examStageQueryWrapper);
        Long datetime = examStages.size() > 0 ? examStages.get(0).getBatchStartTime() : null;
        if (datetime != null) {
            return datetime;
        }
        throw new JkServerException("计算考试任务的开始时间错误");
    }

    //返回考试任务的最迟结束试时间 只是 获取日期
    @Override
    public Long getExamPlanEndTime(String examCode) throws ParseException {
//        Query query = new Query();
//        Criteria.where("examCode").equals(examCode);
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.with(new Sort(Direction.DESC, "batchEndTime"));
//        List<ExamStage> examStages = mongoTemplate.find(query, ExamStage.class);
//        Date datetime = examStages.size() > 0 ? examStages.get(0).getBatchEndTime() : null;
        QueryWrapper<ExamStage> examStageQueryWrapper = new QueryWrapper<>();
        examStageQueryWrapper.lambda().eq(ExamStage::getExamCode, examCode)
                .orderByDesc(ExamStage::getBatchEndTime);
        List<ExamStage> examStages = jkExamStageService.list(examStageQueryWrapper);
        Long datetime = examStages.size() > 0 ? examStages.get(0).getBatchEndTime() : null;
        if (datetime != null) {
            return datetime;
        }
        throw new JkServerException("计算考试任务的最迟结束时间错误");
    }

    @Override
    public Page<ExamStudentTemp> queryExamStudetnsByPages(ExamStudentDto searchCondition, int curPage, int pageSize) {
//        Query query = new Query();
//        Criteria cr = new Criteria();
//        QueryWrapper<ExamStudentTemp> examStudentTempQueryWrapper = new QueryWrapper<>();
//        examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getExamCode, searchCondition.getExamCode())
//                .eq(ExamStudentTemp::getAttachmentId, searchCondition.getAttachmentId());
////        query.addCriteria(Criteria.where("examCode").is(searchCondition.getExamCode()));
////        query.addCriteria(Criteria.where("attachmentId").is(searchCondition.getAttachmentId()));
//        if (StringUtils.isNotBlank(searchCondition.getBatchId())) {
////            query.addCriteria(Criteria.where("batchId").is(searchCondition.getBatchId()));
//            examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getBatchId, searchCondition.getBatchId());
//        }
//        if (StringUtils.isNotBlank(searchCondition.getStageId())) {
////            query.addCriteria(Criteria.where("stageId").is(searchCondition.getStageId()));
//            examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getStageId, searchCondition.getStageId());
//        }
//        if (StringUtils.isNotBlank(searchCondition.getPlaceCode())) {
////            query.addCriteria(Criteria.where("placeCode").is(searchCondition.getPlaceCode()));
//            examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getPlaceCode, searchCondition.getPlaceCode());
//        }
//        if (StringUtils.isNotBlank(searchCondition.getRoomCode())) {
////            query.addCriteria(Criteria.where("roomCode").is(searchCondition.getRoomCode()));
//            examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getRoomCode, searchCondition.getRoomCode());
//        }
//        if (StringUtils.isNotBlank(searchCondition.getCourseCode())) {
////            query.addCriteria(Criteria.where("courseCode").is(searchCondition.getCourseCode()));
//            examStudentTempQueryWrapper.lambda().eq(ExamStudentTemp::getCourseCode, searchCondition.getCourseCode());
//        }
//        if (StringUtils.isNotBlank(searchCondition.getQuerykey())) {
////            query.addCriteria(cr.orOperator(Criteria.where("name").regex(searchCondition.getQuerykey()),
////                    Criteria.where("ticketNo").regex(searchCondition.getQuerykey())));
//            examStudentTempQueryWrapper.lambda().and(
//                    i -> i.like(ExamStudentTemp::getName, searchCondition.getQuerykey())
//                            .or().like(ExamStudentTemp::getTicketNo, searchCondition.getQuerykey()));
//        }
//        long count = jkExamStudentTempService.count(examStudentTempQueryWrapper);
//        long count = this.mongoTemplate.count(query, ExamStudentTemp.class);
//        query.limit(pageSize);
//        query.skip((curPage - 1) * pageSize);
//        List<ExamStudentTemp> examStudentList = this.mongoTemplate.find(query, ExamStudentTemp.class);
//        List<ExamStudentTemp> examStudentList = jkExamStudentTempService.list(examStudentTempQueryWrapper);
        IPage<ExamStudentTemp> examStudentTempIPage = examStudentTempDao.findByExamCode(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(curPage, pageSize),
                searchCondition.getExamCode(), searchCondition.getAttachmentId(), searchCondition.getBatchId(), searchCondition.getStageId(), searchCondition.getPlaceCode(),
                searchCondition.getRoomCode(), searchCondition.getCourseCode(), searchCondition.getQuerykey());
        return new PageImpl<ExamStudentTemp>(examStudentTempIPage.getRecords(), PageRequest.of(curPage - 1, pageSize), examStudentTempIPage.getTotal());
    }

    @Override
    public Page<ExamRoomTemp> queryExamRoomsByPages(ExamRoomTemp searchCondition, int curPage, int pageSize) {
//        Page<ExamRoomTemp> list = examRoomTempDao.findAll(Example.of(searchCondition), PageRequest.of(curPage - 1, pageSize));
//        return list;
        QueryWrapper<ExamRoomTemp> examRoomTempQueryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(searchCondition) && Objects.nonNull(searchCondition.getAttachmentId())) {
            examRoomTempQueryWrapper.lambda().eq(ExamRoomTemp::getAttachmentId, searchCondition.getAttachmentId());
        }
        if (Objects.nonNull(searchCondition) && Objects.nonNull(searchCondition.getExamCode())) {
            examRoomTempQueryWrapper.lambda().eq(ExamRoomTemp::getExamCode, searchCondition.getExamCode());
        }
        if (Objects.nonNull(searchCondition) && Objects.nonNull(searchCondition.getPlaceCode())) {
            examRoomTempQueryWrapper.lambda().eq(ExamRoomTemp::getPlaceCode, searchCondition.getPlaceCode());
        }
//        List<ExamRoomTemp> list = jkExamRoomTempService.list(examRoomTempQueryWrapper);
//        long count = jkExamRoomTempService.count(examRoomTempQueryWrapper);
        IPage<ExamRoomTemp> examRoomTempIPage = examRoomTempDao.findByExamCode(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(curPage, pageSize),
                searchCondition.getExamCode(), searchCondition.getAttachmentId(), searchCondition.getPlaceCode());
        return new PageImpl<ExamRoomTemp>(examRoomTempIPage.getRecords(), PageRequest.of(curPage - 1, pageSize), examRoomTempIPage.getTotal());
    }

    @Override
    public List<Map<String, Object>> distinctPlaceCodeExamRoomTemp(String examCode, Long attachmentId) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Criteria criteria = new Criteria();
//        criteria.andOperator(Criteria.where("examCode").is(examCode), Criteria.where("attachmentId").is(attachmentId));
//        TypedAggregation<ExamRoomTemp> aggregation = Aggregation.newAggregation(
//                ExamRoomTemp.class,
//                Aggregation.match(criteria),
//                Aggregation.group("placeCode", "placeName"),
//                Aggregation.sort(Direction.ASC, "placeCode")
//        ).withOptions(aggregationOptions);
//        AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamRoomTemp.class, DBObject.class);
//        List<DBObject> list = map.getMappedResults();
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map> results = examRoomTempDao.findByExamCodeAndAttachmentIdByMap(examCode, attachmentId);
//        for (DBObject object : list) {
        if (!CollectionUtils.isEmpty(results)) {
            for (Map m : results) {
                Map<String, Object> data = new HashMap<>();
//                data.put("name", object.get("placeName"));
//                data.put("value", object.get("placeCode"));
                data.put("name", m.get("placeName"));
                data.put("value", m.get("placeCode"));
                result.add(data);
            }
        }
//        }
        return result;
    }

    @Override
    public List<Map<String, Object>> distinctRoomCodeExamRoomTemp(String examCode, Long attachmentId) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Criteria criteria = new Criteria();
//        criteria.andOperator(Criteria.where("examCode").is(examCode), Criteria.where("attachmentId").is(attachmentId));
//        TypedAggregation<ExamRoomTemp> aggregation = Aggregation.newAggregation(
//                ExamRoomTemp.class,
//                Aggregation.match(criteria),
//                Aggregation.group("roomCode", "roomName"),
//                Aggregation.sort(Direction.ASC, "roomCode")
//        ).withOptions(aggregationOptions);
//        AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamRoomTemp.class, DBObject.class);
//        List<DBObject> list = map.getMappedResults();
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map> results = examRoomTempDao.findByExamCodeAndAttachmentIdGroupByRoomCodeByMap(examCode, attachmentId);
//        for (DBObject object : list) {
        if (!CollectionUtils.isEmpty(results)) {
            for (Map m : results) {
                Map<String, Object> data = new HashMap<>();
//            data.put("name", object.get("roomName"));
//            data.put("value", object.get("roomCode"));
                data.put("name", m.get("roomName"));
                data.put("value", m.get("roomCode"));
                result.add(data);
            }
        }
//        }
        return result;
    }

    @Override
    public List<Map<String, Object>> distinctCourseCodeStudentTemp(String examCode, Long attachmentId, ExamType examType) {
        if (examType.equals(ExamType.SOLFEGE)) {
            return new ArrayList<>();
        }
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Criteria criteria = new Criteria();
//        criteria.andOperator(Criteria.where("examCode").is(examCode), Criteria.where("attachmentId").is(attachmentId));
        List<Map<String, Object>> result = new ArrayList<>();
        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            TypedAggregation<ExamStudentTemp> aggregation = Aggregation.newAggregation(
//                    ExamStudentTemp.class,
//                    Aggregation.match(criteria),
//                    Aggregation.group("courseCode", "courseName"),
//                    Aggregation.sort(Direction.ASC, "courseCode"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStudentTemp.class, DBObject.class);
//            List<DBObject> list = map.getMappedResults();
//            if (list.size() < limit) {
//                over = true;
//            }
//            for (DBObject object : list) {
            IPage<Map> examStudentTempIPage = examStudentTempDao.findByExamCodeAndAttachmentIdByMap(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode, attachmentId);
            if (!CollectionUtils.isEmpty(examStudentTempIPage.getRecords())) {
                for (Map m : examStudentTempIPage.getRecords()) {
                    Map<String, Object> data = new HashMap<>();
//                    data.put("name", object.get("courseName"));
//                    data.put("value", object.get("courseCode"));
                    data.put("name", m.get("courseName"));
                    data.put("value", m.get("courseCode"));
                    result.add(data);
                }
                if (examStudentTempIPage.getRecords().size() < limit) {
                    over = true;
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> distinctBatchIdStudentTemp(String examCode, Long attachmentId, ExamType examType) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Criteria criteria = new Criteria();
//        criteria.andOperator(Criteria.where("examCode").is(examCode), Criteria.where("attachmentId").is(attachmentId));
//        TypedAggregation<ExamStageTemp> aggregation = Aggregation.newAggregation(
//                ExamStageTemp.class,
//                Aggregation.match(criteria),
//                Aggregation.group("batchId", "batchName"),
//                Aggregation.sort(Direction.ASC, "batchId")
//        ).withOptions(aggregationOptions);
//        AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStageTemp.class, DBObject.class);
//        List<DBObject> list = map.getMappedResults();
        List<Map> list = examStageTempDao.findByExamCodeAndAttachmentIdByMap(examCode, attachmentId);
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map m : list) {
            Map<String, Object> data = new HashMap<>();
//            data.put("name", object.get("batchName"));
//            data.put("value", object.get("batchId"));
            data.put("name", m.get("batchName"));
            data.put("value", m.get("batchId"));
            result.add(data);
        }
        return result;

    }

    //获取批次的开始时间
    @Override
    public Long getBatchStartTime(String examCode, String batchId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("batchId").is(batchId));
//        List<ExamStage> examStages = mongoTemplate.find(query, ExamStage.class);
        QueryWrapper<ExamStage> examStageQueryWrapper = new QueryWrapper<>();
        examStageQueryWrapper.lambda().eq(ExamStage::getExamCode, examCode)
                .eq(ExamStage::getBatchId, batchId);
        List<ExamStage> examStages = jkExamStageService.list(examStageQueryWrapper);
        return examStages.size() > 0 ? examStages.get(0).getBatchStartTime() : null;
    }

    @Override
    public String createExamCode() {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("used").is(false));
//        List<ExamCode> examCodes = mongoTemplate.find(query, ExamCode.class);
        Long schoolId = (Long) ServletUtil.getRequestHeaderSchoolId();
        QueryWrapper<ExamCode> examCodeQueryWrapper = new QueryWrapper<>();
        examCodeQueryWrapper.lambda().eq(ExamCode::getUsed, false);
        examCodeQueryWrapper.lambda().eq(ExamCode::getSchoolId, schoolId);
        List<ExamCode> examCodes = jkExamCodeService.list(examCodeQueryWrapper);
        if (examCodes.size() > 0) {
            return examCodes.get(0).getExamCode();
        }
        while (true) {
            String tempCode = this.makeExamCode();
            if (!isAlreadyExists(tempCode)) {
                ExamCode examCode = new ExamCode();
                examCode.setId(SystemConstant.getDbUuid());
                examCode.setExamCode(tempCode);
                examCode.setUsed(false);
                examCode.setSchoolId(schoolId);
                jkExamCodeService.saveOrUpdate(examCode);
                return tempCode;
            }
        }
    }

    @Override
    public ExamPlan updateStatus(String id, ExamStatus status) {
        ExamPlan examPlan = examPlanDao.findById(Long.parseLong(id));
        examPlan.setExamStatus(status);
        examPlanService.saveOrUpdate(examPlan);
        return examPlan;
    }


    @Override
    public List<Map<String, Object>> distinctStageIdStudentTemp(String examCode, Long attachmentId, String batchId, ExamType examType) {
        if (examType.equals(ExamType.SOLFEGE)) {
            return new ArrayList<>();
        }
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        TypedAggregation<ExamStageTemp> aggregation = null;
//        if (StringUtils.isNotEmpty(batchId)) {
//            Criteria criteria = new Criteria();
//            criteria.andOperator(
//                    Criteria.where("examCode").is(examCode),
//                    Criteria.where("attachmentId").is(attachmentId),
//                    Criteria.where("batchId").is(batchId));
//            aggregation = Aggregation.newAggregation(
//                    ExamStageTemp.class,
//                    Aggregation.match(criteria),
//                    Aggregation.group("batchId", "stageId"),
//                    Aggregation.sort(Direction.ASC, "stageId")
//            ).withOptions(aggregationOptions);
//        }
//        else {
//            Criteria criteria = new Criteria();
//            criteria.andOperator(
//                    Criteria.where("examCode").is(examCode),
//                    Criteria.where("attachmentId").is(attachmentId));
//            aggregation = Aggregation.newAggregation(
//                    ExamStageTemp.class,
//                    Aggregation.match(criteria),
//                    Aggregation.group("batchId", "stageId")
//            ).withOptions(aggregationOptions);
//        }
//        AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStageTemp.class, DBObject.class);
//        List<DBObject> list = map.getMappedResults();
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map> list = examStageTempDao.findByExamCodeAndAttachmentIdAndBatchId(examCode, attachmentId, batchId);
        for (Map m : list) {
            Map<String, Object> data = new HashMap<>();
            //场次没有名称，名称默认取ID值
//            if (object.get("stageId") != null) {
//                data.put("name", object.get("stageId"));
//                data.put("value", object.get("stageId"));
//                result.add(data);
//            }
            if (m.get("stageId") != null) {
                data.put("name", m.get("stageId"));
                data.put("value", m.get("stageId"));
                result.add(data);
            }
        }
        return result;
    }

    @Override
    public List<ExamPlan> findByStatus(ExamStatus status, User creator) {
//        Query query = new Query();
//        if (status != null) {
//            query.addCriteria(Criteria.where("examStatus").is(status));
//        }
//        if (creator != null && !creator.getUserName().equals("super")) {
//            query.addCriteria(Criteria.where("creatorId").is(creator.getId()));
//        }
//        query.addCriteria(Criteria.where("enable").is(true));
//        query.with(new Sort(Direction.DESC, "createTime"));
//        List<ExamPlan> examPlans = mongoTemplate.find(query, ExamPlan.class);
        QueryWrapper<ExamPlan> examPlanQueryWrapper = new QueryWrapper<>();
        if (status != null) {
            examPlanQueryWrapper.lambda().eq(ExamPlan::getExamStatus, status);
        }
//        if (creator != null && !creator.getUserName().equals("super")) {
//            examPlanQueryWrapper.lambda().eq(ExamPlan::getCreatorId, creator.getId());
//        }
        Long schoolId = (Long) ServletUtil.getRequestHeaderSchoolId();
        if (Objects.nonNull(schoolId) && schoolId.longValue() > 0) {
            examPlanQueryWrapper.lambda().eq(ExamPlan::getSchoolId, schoolId);
        }
        examPlanQueryWrapper.lambda().eq(ExamPlan::getEnable, true)
                .orderByDesc(ExamPlan::getCreateTime);
        List<ExamPlan> examPlans = examPlanService.list(examPlanQueryWrapper);
        return examPlans;
    }

    @Override
    public ExamCode findExamCode(String examCode) {
        List<ExamCode> list = examCodeDao.findByExamCode(examCode);
        return list.size() > 0 ? list.get(0) : null;
    }

    @Override
    public List<ExamStage> findStageByExamCode(String examCode) {
        return examStageDao.findByExamCode(examCode);
    }

    @Override
    public List<Map<String, Object>> distinctPlaceCodeExamStudentTemp(String examCode) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
        List<Map<String, Object>> result = new ArrayList<>();
        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            TypedAggregation<ExamStudentTemp> aggregation = Aggregation.newAggregation(
//                    ExamStudentTemp.class,
//                    Aggregation.match(Criteria.where("examCode").is(examCode)),
//                    Aggregation.group("examCode", "placeCode"),
//                    Aggregation.sort(Direction.ASC, "placeCode"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStudentTemp.class, DBObject.class);
//            List<DBObject> list = map.getMappedResults();
//            if (list.size() < limit) {
//                over = true;
//            }
//            for (DBObject object : list) {
            IPage<Map> examStudentTempIPage = examStudentTempDao.findByExamCodeByMap(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode);
            if (!CollectionUtils.isEmpty(examStudentTempIPage.getRecords())) {
                for (Map m : examStudentTempIPage.getRecords()) {
                    Map<String, Object> data = new HashMap<>();
                    //场次没有名称，名称默认取ID值
//                    if (object.get("placeCode") != null) {
//                        data.put("name", object.get("placeCode"));
//                        data.put("value", object.get("placeCode"));
//                        result.add(data);
//                    }
                    if (m.get("placeCode") != null) {
                        data.put("name", m.get("placeCode"));
                        data.put("value", m.get("placeCode"));
                        result.add(data);
                    }
                }
                if (examStudentTempIPage.getRecords().size() < limit) {
                    over = true;
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> distinctRoomCodeExamStudentTemp(String examCode, String placeCode) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Criteria criteria = new Criteria();
//        if (StringUtils.isNotEmpty(placeCode)) {
//            criteria.andOperator(Criteria.where("examCode").is(examCode), Criteria.where("placeCode").is(placeCode));
//        } else {
//            criteria = Criteria.where("examCode").is(examCode);
//        }
        List<Map<String, Object>> result = new ArrayList<>();

        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            TypedAggregation<ExamStudentTemp> aggregation = Aggregation.newAggregation(
//                    ExamStudentTemp.class,
//                    Aggregation.match(criteria),
//                    Aggregation.group("placeCode", "roomCode"),
//                    Aggregation.sort(Direction.ASC, "roomCode"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStudentTemp.class, DBObject.class);
//            List<DBObject> list = map.getMappedResults();
//            if (list.size() < limit) {
//                over = true;
//            }
//            for (DBObject object : list) {
            IPage<Map> examStudentTempIPage = examStudentTempDao.findByExamCodeAndPlaceCodeByMap(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode, placeCode);
            if (!CollectionUtils.isEmpty(examStudentTempIPage.getRecords())) {
                for (Map m : examStudentTempIPage.getRecords()) {
                    Map<String, Object> data = new HashMap<>();
                    //场次没有名称，名称默认取ID值
//                    if (object.get("roomCode") != null) {
//                        data.put("name", object.get("roomCode"));
//                        data.put("value", object.get("roomCode"));
//                        result.add(data);
//                    }
                    if (m.get("roomCode") != null) {
                        data.put("name", m.get("roomCode"));
                        data.put("value", m.get("roomCode"));
                        result.add(data);
                    }
                }
                if (examStudentTempIPage.getRecords().size() < limit) {
                    over = true;
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> distinctBatchExamStudent(String examCode) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
        List<Map<String, Object>> result = new ArrayList<>();
        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            TypedAggregation<ExamStudent> aggregation = Aggregation.newAggregation(
//                    ExamStudent.class,
//                    Aggregation.match(Criteria.where("examCode").is(examCode)),
//                    Aggregation.group("examCode", "batchId", "batchName"),
//                    Aggregation.project("batchId", "batchName"),
//                    Aggregation.sort(Direction.ASC, "batchId"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStudent.class, DBObject.class);
//            List<DBObject> list = map.getMappedResults();
//            if (list.size() < limit) {
//                over = true;
//            }
//            for (DBObject object : list) {
            IPage<Map> examStudentIPage = examStudentDao.findByExamCodeByMap(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode);
            if (!CollectionUtils.isEmpty(examStudentIPage.getRecords())) {
                for (Map m : examStudentIPage.getRecords()) {
                    Map<String, Object> data = new HashMap<>();
                    //场次没有名称，名称默认取ID值
//                    if (object.get("batchId") != null) {
//                        data.put("name", object.get("batchName"));
//                        data.put("value", object.get("batchId"));
//                        result.add(data);
//                    }
                    if (m.get("batchId") != null) {
                        data.put("name", m.get("batchName"));
                        data.put("value", m.get("batchId"));
                        result.add(data);
                    }
                }
                if (examStudentIPage.getRecords().size() < limit) {
                    over = true;
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return result;
    }

    //判断某一个考试计划是否可以编辑
    @Override
    public boolean canEdit(String examCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        long count = mongoTemplate.count(query, ExamStudentAnswer.class);
        QueryWrapper<ExamStudentAnswer> examStudentAnswerQueryWrapper = new QueryWrapper<>();
        examStudentAnswerQueryWrapper.lambda().eq(ExamStudentAnswer::getExamCode, examCode);
        long count = examStudentAnswerService.count(examStudentAnswerQueryWrapper);
        return count <= 0;
    }

    @Override
    public List<ExamStudentAdditionalTemp> studentAdditionalTempGroupBy(String examCode, Long attachmentId) {
//        DBObject dbObject = new BasicDBObject();
//        dbObject.put("exam_code", examCode);
//        dbObject.put("attachment_id", attachmentId);
//        DBObject projection = new BasicDBObject();
//        projection.put("_id", 0);
//        projection.put("student_id", 1);
//        projection.put("course_code", 1);
//        LOGGER.info("@@@@@ examCode:" + examCode);
//        LOGGER.info("@@@@@ attachment_id:" + attachmentId);
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_student_additional_temp").find(dbObject, projection);
//        List<DBObject> list = new ArrayList<DBObject>();
//        while (dbCursor.hasNext()) {
//            DBObject document = dbCursor.next();
//            LOGGER.info("@@@@@:" + document.toString());
//            list.add(document);
//        }
//        dbCursor.close();
        QueryWrapper<ExamStudentAdditionalTemp> examStudentAdditionalTempQueryWrapper = new QueryWrapper<>();
        examStudentAdditionalTempQueryWrapper.lambda().eq(ExamStudentAdditionalTemp::getExamCode, examCode)
                .eq(ExamStudentAdditionalTemp::getAttachmentId, attachmentId);
        List<ExamStudentAdditionalTemp> list = jkExamStudentAdditionalTempService.list(examStudentAdditionalTempQueryWrapper);
        LOGGER.info("@@studentAdditionalTempGroupBy size:" + list.size());
        return list;
    }

    @Override
    public void updateRoomKjAlready(String examCode, String placeCode, String roomCode) {
        if (StringUtils.isEmpty(examCode) || StringUtils.isEmpty(placeCode) || StringUtils.isEmpty(roomCode)) {
            throw JkServerException.withFieldValidateError("参数错误,examCode,placeCode,roomCode都不能够为空");
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("placeCode").is(placeCode));
//        query.addCriteria(Criteria.where("roomCode").is(roomCode));
//        List<ExamRoom> examRooms = mongoTemplate.find(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, examCode)
                .eq(ExamRoom::getPlaceCode, placeCode)
                .eq(ExamRoom::getRoomCode, roomCode);
        List<ExamRoom> examRooms = jkExamRoomService.list(examRoomQueryWrapper);
        if (examRooms.size() == 0) {
            throw JkServerException.withFieldValidateError("参数错误,examCode,placeCode,roomCode对应的考场不存在");
        }
        ExamRoom examRoom = examRooms.get(0);
        examRoom.setKjAlready(true);
        jkExamRoomService.saveOrUpdate(examRoom);
    }

    @Override
    public void updateRoomKwAlready(String examCode, String placeCode, String roomCode, ExamKwProgressType type) {
        if (StringUtils.isEmpty(examCode) || StringUtils.isEmpty(placeCode) || StringUtils.isEmpty(roomCode)) {
            throw JkServerException.withFieldValidateError("参数错误,examCode,placeCode,roomCode都不能够为空");
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("placeCode").is(placeCode));
//        query.addCriteria(Criteria.where("roomCode").is(roomCode));
//        List<ExamRoom> examRooms = mongoTemplate.find(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, examCode)
                .eq(ExamRoom::getPlaceCode, placeCode)
                .eq(ExamRoom::getRoomCode, roomCode);
        List<ExamRoom> examRooms = jkExamRoomService.list(examRoomQueryWrapper);
        if (examRooms.size() == 0) {
            throw JkServerException.withFieldValidateError("参数错误,examCode,placeCode,roomCode对应的考场不存在");
        }
        ExamRoom examRoom = examRooms.get(0);
        if (examRoom.getKwKcAlready() == null) {
            examRoom.setKwKcAlready(false);
        }
        if (examRoom.getKwPaperAlready() == null) {
            examRoom.setKwPaperAlready(false);
        }
        if (examRoom.getKwUncolilingAlready() == null) {
            examRoom.setKwUncolilingAlready(false);
        }
        if (type.equals(ExamKwProgressType.KW)) {
            examRoom.setKwKcAlready(true);
        } else if (type.equals(ExamKwProgressType.PAPER)) {
            examRoom.setKwPaperAlready(true);
        } else if (type.equals(ExamKwProgressType.UNCOILING)) {
            examRoom.setKwUncolilingAlready(true);
        } else {
            throw JkServerException.withFieldValidateError("错误的类型:" + type);
        }
        jkExamRoomService.saveOrUpdate(examRoom);
    }

    /**
     * 保存考试计划
     *
     * @param examCode
     * @param examTask
     */
    @Override
    public void saveExamPlanByTask(String examCode, ExamTask examTask) {
        ExamPlan examPlan = this.findByExamCode(examCode);
        examPlan.setExamTaskId(examTask.getId());
//        mongoTemplate.save(examPlan);
        examPlanService.saveOrUpdate(examPlan);
    }

    @Override
    public List<Map<String, Object>> distinctBatch(String examCode) {
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
        List<Map<String, Object>> result = new ArrayList<>();
        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            TypedAggregation<ExamStage> aggregation = Aggregation.newAggregation(
//                    ExamStage.class,
//                    Aggregation.match(Criteria.where("examCode").is(examCode)),
//                    Aggregation.group("examCode", "batchId", "batchName"),
//                    Aggregation.project("batchId", "batchName"),
//                    Aggregation.sort(Direction.ASC, "batchId"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStage.class, DBObject.class);
//            List<DBObject> list = map.getMappedResults();
//            if (list.size() < limit) {
//                over = true;
//            }
//            for (DBObject object : list) {
            IPage<Map> examstageIPage = examStageDao.findByExamCodeByMap(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode);
            if (!CollectionUtils.isEmpty(examstageIPage.getRecords())) {
                for (Map m : examstageIPage.getRecords()) {
                    Map<String, Object> data = new HashMap<>();
                    //场次没有名称，名称默认取ID值
//                    if (object.get("batchId") != null) {
//                        data.put("name", object.get("batchName"));
//                        data.put("value", object.get("batchId"));
//                        result.add(data);
//                    }
                    if (m.get("batchId") != null) {
                        data.put("name", m.get("batchName"));
                        data.put("value", m.get("batchId"));
                        result.add(data);
                    }
                }
                if (examstageIPage.getRecords().size() < limit) {
                    over = true;
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return result;
    }


}
