package com.qmth.jkserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dao.ExamRepeatRecordDao;
import com.qmth.jkserver.dao.ExamStudentAnswerDao;
import com.qmth.jkserver.dao.ExamStudentDao;
import com.qmth.jkserver.dto.ExamStudenDetailDto;
import com.qmth.jkserver.dto.ExamStudentCountDto;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.service.*;
import org.apache.commons.lang3.StringUtils;
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.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class ExamKwHZServiceImpl implements ExamKwHZService {

//	@Autowired
//	private MongoOperations mongoTemplate;

    @Resource
    ExamStudentDao examStudentDao;

    @Resource
    JkExamRoomService jkExamRoomService;

    @Resource
    ExamStudentAnswerDao examStudentAnswerDao;

    @Resource
    JkExamAbortService jkExamAbortService;

    @Resource
    JkExamAbsentService jkExamAbsentService;

    @Resource
    JkExamCheatService jkExamCheatService;

    @Resource
    JkExamRepeatRecordService jkExamRepeatRecordService;

    @Resource
    ExamRepeatRecordDao examRepeatRecordDao;

    @Override
    public Page<ExamStudentCountDto> statisticKwHZDetails(String code, String batchId,
                                                          String placeCode, String placeName, String roomCode, Integer pageNo, Integer pageSize) {
        //Sort.Order order1 = new Sort.Order(Direction.ASC, "batchId");
        //Sort.Order order2 = new Sort.Order(Direction.ASC, "stageId");
//        Sort.Order order3 = new Sort.Order(Direction.ASC, "placeCode");
//        Sort.Order order4 = new Sort.Order(Direction.ASC, "roomCode");
//        Sort sort = new Sort(order3, order4);
//        Criteria criteria = Criteria.where("examCode").is(code);
//        if (StringUtils.isNotEmpty(batchId)) {
//            criteria = criteria.and("batchId").is(batchId);
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
//            criteria = criteria.and("placeCode").is(placeCode);
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
//            criteria = criteria.and("roomCode").is(roomCode);
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
//            criteria = criteria.and("placeCode").in(placeCodeLike(code, placeName));
//        }
        //允许使用磁盘缓存
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        Aggregation totalAgg = Aggregation.newAggregation(ExamStudent.class,
//                Aggregation.match(criteria),
//                Aggregation.group("stageId", "batchId", "placeCode", "roomCode").count().as("fullStudentNum")).withOptions(aggregationOptions);
//        AggregationResults<DBObject> tresult = mongoTemplate.aggregate(totalAgg, ExamStudent.class,
//                DBObject.class);
//        int total = tresult.getMappedResults().size();
//        List<Map> listTotal = examStudentDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceName(code, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(code, placeName), roomCode, placeName);
//        int total = listTotal.size();
//        Aggregation agg = Aggregation.newAggregation(ExamStudent.class,
//                Aggregation.match(criteria),
//                Aggregation.group("stageId", "batchId", "placeCode", "roomCode", "batchName").count().as("fullStudentNum"),
//                Aggregation.sort(sort),
//                Aggregation.skip((long) (pageNo - 1) * pageSize),
//                Aggregation.limit(pageSize),
//                Aggregation.project("stageId", "batchId", "batchName", "placeCode", "roomCode", "fullStudentNum")
//        ).withOptions(aggregationOptions);
//        AggregationResults<DBObject> result = mongoTemplate.aggregate(agg, ExamStudent.class, DBObject.class);
//        List<DBObject> fullStudentList = result.getMappedResults();
        IPage<Map> examStudentIpage = examStudentDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize)
                , code, batchId, placeCodeLike(code, placeName), roomCode, placeName);
        List<ExamStudentCountDto> resultList = new ArrayList<ExamStudentCountDto>();
        for (Map countDto : examStudentIpage.getRecords()) {
            ExamStudentCountDto examStudentCountDto = new ExamStudentCountDto();
            String stageId = (String) countDto.get("stageId");
            String bid = (String) countDto.get("batchId");
            String pCode = (String) countDto.get("placeCode");
            String rCode = (String) countDto.get("roomCode");
            String batchName = (String) countDto.get("batchName");
            long totalNum = Long.parseLong(String.valueOf(countDto.get("fullStudentNum")));
            examStudentCountDto.setStageId(stageId);
            examStudentCountDto.setBatchId(bid);
            examStudentCountDto.setPlaceCode(pCode);
            examStudentCountDto.setRoomCode(rCode);
            examStudentCountDto.setBatchName(batchName);
            resultList.add(examStudentCountDto);
            // 计算当前批次、当前考次下面的缺考人数
            examStudentCountDto.setFullStudentNum(totalNum);
//            Query query = new Query();
//            query.addCriteria(Criteria.where("examCode").is(code));
//            query.addCriteria(Criteria.where("student.stageId").is(stageId));
//            query.addCriteria(Criteria.where("student.batchId").is(bid));
//            query.addCriteria(Criteria.where("student.placeCode").is(pCode));
//            query.addCriteria(Criteria.where("student.roomCode").is(rCode));
//            query.addCriteria(Criteria.where("isAbsent").is(true));
//            long absentStudentNum = mongoTemplate.count(query, ExamStudentAnswer.class);
            long absentStudentNum = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(code, stageId, bid, new HashSet<>(Arrays.asList(pCode)), rCode, true, null, null, null);
            examStudentCountDto.setAbsentStudentNum(absentStudentNum);
//            Query roomQuery = new Query();
//            roomQuery.addCriteria(Criteria.where("examCode").is(code));
//            roomQuery.addCriteria(Criteria.where("placeCode").is(pCode));
//            roomQuery.addCriteria(Criteria.where("roomCode").is(rCode));
//            List<ExamRoom> list = mongoTemplate.find(roomQuery, ExamRoom.class);
            QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
            examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, code)
                    .eq(ExamRoom::getPlaceCode, pCode)
                    .eq(ExamRoom::getRoomCode, rCode);
            List<ExamRoom> list = jkExamRoomService.list(examRoomQueryWrapper);
            if (list.size() > 0) {
                examStudentCountDto.setPlaceName(list.get(0).getPlaceName());
                examStudentCountDto.setRoomName(list.get(0).getRoomName());
            }
            // 计算当前批次、当前考次下面的实考人数
//            Query rquery = new Query();
//            rquery.addCriteria(Criteria.where("examCode").is(code));
//            rquery.addCriteria(Criteria.where("student.stageId").is(stageId));
//            rquery.addCriteria(Criteria.where("student.batchId").is(bid));
//            rquery.addCriteria(Criteria.where("student.placeCode").is(pCode));
//            rquery.addCriteria(Criteria.where("student.roomCode").is(rCode));
//            rquery.addCriteria(Criteria.where("isAbsent").is(false));
//            long realStudentNum = mongoTemplate.count(rquery, ExamStudentAnswer.class);
            long realStudentNum = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(code, stageId, bid, new HashSet<>(Arrays.asList(pCode)), rCode, false, null, null, null);
            examStudentCountDto.setRealityStudentNum(realStudentNum);
        }
        return new PageImpl<ExamStudentCountDto>(resultList, PageRequest.of(pageNo - 1, pageSize), examStudentIpage.getTotal());
    }

    @Override
    public Page<ExamStudenDetailDto> queryKwHZDetails(String examCode, String batchId,
                                                      String placeCode, String placeName, String roomCode,
                                                      String condition, int pageNo, int pageSize) {
        if ("repeat".equals(condition)) {
            return queryRepeat(examCode, batchId, placeCode, placeName, roomCode, condition, pageNo, pageSize);
        }
        List<ExamStudentAnswer> list = new ArrayList<ExamStudentAnswer>();
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        if (StringUtils.isNotEmpty(batchId)) {
//            query.addCriteria(Criteria.where("student.batchId").is(batchId));
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
//            query.addCriteria(Criteria.where("student.placeCode").is(placeCode));
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
//            query.addCriteria(Criteria.where("student.roomCode").is(roomCode));
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
//            query.addCriteria(Criteria.where("student.placeCode").in(placeCodeLike(examCode, placeName)));
//        }
//        long total = 0;
        Boolean absent = null, cheat = null, abort = null;
        if ("absent".equals(condition)) {
//            query.addCriteria(Criteria.where("isAbsent").is(true));
            absent = true;
        } else if ("cheat".equals(condition)) {
//            query.addCriteria(Criteria.where("isCheat").is(true));
            cheat = true;
        } else if ("abort".equals(condition)) {
//            query.addCriteria(Criteria.where("isAbort").is(true));
            abort = true;
        } else {
            throw JkServerException.withFieldValidateError("错误的查询条件:" + condition);
        }
//        total = this.mongoTemplate.count(query, ExamStudentAnswer.class);
//        total = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(examCode, null, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, absent, cheat, abort, placeName);
//        Sort.Order order1 = new Sort.Order(Direction.ASC, "student.ticketNo");
//        Sort.Order order2 = new Sort.Order(Direction.ASC, "student.courseCode");
//        query.with(new Sort(order1, order2));
//        query.limit(pageSize);
//        query.skip((pageNo - 1) * pageSize);
//        list = this.mongoTemplate.find(query, ExamStudentAnswer.class);
        IPage<Map> examstudentAnswerIpage = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize), examCode, null, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, absent, cheat, abort, placeName);
        List<ExamStudenDetailDto> detailDtos = new ArrayList<ExamStudenDetailDto>();
        for (Map answer : examstudentAnswerIpage.getRecords()) {
            detailDtos.add(convert(answer));
        }
        return new PageImpl<ExamStudenDetailDto>(detailDtos, PageRequest.of(pageNo - 1, pageSize), examstudentAnswerIpage.getTotal());
    }

    //查询重考记录
    private Page<ExamStudenDetailDto> queryRepeat(String examCode, String batchId,
                                                  String placeCode, String placeName, String roomCode,
                                                  String condition, int pageNo, int pageSize) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        QueryWrapper<ExamRepeatRecord> examRepeatRecordQueryWrapper = new QueryWrapper<>();
//        examRepeatRecordQueryWrapper.lambda().eq(ExamRepeatRecord::getExamCode, examCode);
//        if (StringUtils.isNotEmpty(batchId)) {
////            query.addCriteria(Criteria.where("batchId").is(batchId));
//            examRepeatRecordQueryWrapper.lambda().eq(ExamRepeatRecord::getBatchId, batchId);
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
////            query.addCriteria(Criteria.where("placeCode").is(placeCode));
//            examRepeatRecordQueryWrapper.lambda().eq(ExamRepeatRecord::getPlaceCode, placeCode);
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
////            query.addCriteria(Criteria.where("roomCode").is(roomCode));
//            examRepeatRecordQueryWrapper.lambda().eq(ExamRepeatRecord::getRoomCode, roomCode);
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
////            query.addCriteria(Criteria.where("placeCode").in(placeCodeLike(examCode, placeName)));
//            examRepeatRecordQueryWrapper.lambda().in(ExamRepeatRecord::getPlaceCode, placeCodeLike(examCode, placeName));
//        }
////        long total = this.mongoTemplate.count(query, ExamRepeatRecord.class);
//        long total = jkExamRepeatRecordService.count(examRepeatRecordQueryWrapper);
//        long total = examRepeatRecordDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceNameByCount(examCode, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, placeName);

//        Sort.Order order1 = new Sort.Order(Direction.ASC, "ticketNo");
//        Sort.Order order2 = new Sort.Order(Direction.ASC, "courseCode");
//        query.with(new Sort(order1, order2));
//        query.limit(pageSize);
//        query.skip((pageNo - 1) * pageSize);
//        List<ExamRepeatRecord> list = this.mongoTemplate.find(query, ExamRepeatRecord.class);
        IPage<ExamRepeatRecord> list = examRepeatRecordDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize), examCode, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, placeName);
        List<ExamStudenDetailDto> detailDtos = new ArrayList<ExamStudenDetailDto>();
        for (ExamRepeatRecord record : list.getRecords()) {
            detailDtos.add(convert(record));
        }
        return new PageImpl<ExamStudenDetailDto>(detailDtos, PageRequest.of(pageNo - 1, pageSize), list.getTotal());
    }

    private Set<String> placeCodeLike(String examCode, String placeName) {
//        Set<String> set = new HashSet<String>();
//        DBObject query = new BasicDBObject();
//        query.put("exam_code", examCode);
//        if (StringUtils.isNotEmpty(placeName)) {
//            DBObject regex = new BasicDBObject();
//            Pattern pattern = Pattern.compile("^.*" + placeName + ".*$", Pattern.CASE_INSENSITIVE);
//            regex.put("$regex", pattern);
//            query.put("place_name", regex);
//        }
//        DBObject projection = new BasicDBObject();
//        projection.put("place_code", 1);
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_room").find(query, projection);
//        while (dbCursor.hasNext()) {
//            DBObject dbObject = dbCursor.next();
//            set.add(dbObject.get("place_code").toString());
//        }
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        examRoomQueryWrapper.lambda().eq(ExamRoom::getRoomCode, examCode);
        if (StringUtils.isNotEmpty(placeName)) {
            examRoomQueryWrapper.lambda().like(ExamRoom::getPlaceName, placeName);
        }
        List<ExamRoom> examRoomList = jkExamRoomService.list(examRoomQueryWrapper);
        return examRoomList.stream().map(e -> e.getPlaceCode()).collect(Collectors.toSet());
    }

    @Override
    public Map<String, Long> statisticKwHZ(String examCode, String batchId,
                                           String placeCode, String placeName, String roomCode) {
        Map<String, Long> result = new LinkedHashMap<>();
//        Query tquery = new Query();
//        tquery.addCriteria(Criteria.where("examCode").is(examCode));
//        QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
//        examStudentQueryWrapper.lambda().eq(ExamStudent::getExamCode, examCode);
//        if (StringUtils.isNotEmpty(batchId)) {
////            tquery.addCriteria(Criteria.where("batchId").is(batchId));
//            examStudentQueryWrapper.lambda().eq(ExamStudent::getBatchId, batchId);
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
////            tquery.addCriteria(Criteria.where("placeCode").is(placeCode));
//            examStudentQueryWrapper.lambda().eq(ExamStudent::getPlaceCode, placeCode);
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
////            tquery.addCriteria(Criteria.where("roomCode").is(roomCode));
//            examStudentQueryWrapper.lambda().eq(ExamStudent::getRoomCode, roomCode);
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
////            tquery.addCriteria(Criteria.where("placeCode").in(placeCodeLike(examCode, placeName)));
//            examStudentQueryWrapper.lambda().in(ExamStudent::getPlaceCode, placeCodeLike(examCode, placeName));
//        }
////        long totalCount = mongoTemplate.count(tquery, ExamStudent.class);
//        long totalCount = examStudentService.count(examStudentQueryWrapper);

        long totalCount = examStudentDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceNameCount(examCode, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, placeName);
        result.put("full", totalCount);
//        Query aquery = new Query();
//        aquery.addCriteria(Criteria.where("examCode").is(examCode));
//        if (StringUtils.isNotEmpty(batchId)) {
//            aquery.addCriteria(Criteria.where("student.batchId").is(batchId));
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
//            aquery.addCriteria(Criteria.where("student.placeCode").is(placeCode));
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
//            aquery.addCriteria(Criteria.where("student.roomCode").is(roomCode));
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
//            aquery.addCriteria(Criteria.where("student.placeCode").in(placeCodeLike(examCode, placeName)));
//        }
//        aquery.addCriteria(Criteria.where("isAbsent").is(true));
//        long absentCount = mongoTemplate.count(aquery, ExamStudentAnswer.class);
        long absentCount = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(examCode, null, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, true, null, null, placeName);
        result.put("absent", absentCount);
//        Query rquery = new Query();
//        rquery.addCriteria(Criteria.where("examCode").is(examCode));
//        if (StringUtils.isNotEmpty(batchId)) {
//            rquery.addCriteria(Criteria.where("student.batchId").is(batchId));
//        }
//        if (StringUtils.isNotEmpty(placeCode)) {
//            rquery.addCriteria(Criteria.where("student.placeCode").is(placeCode));
//        }
//        if (StringUtils.isNotEmpty(roomCode)) {
//            rquery.addCriteria(Criteria.where("student.roomCode").is(roomCode));
//        }
//        if (StringUtils.isEmpty(placeCode) && StringUtils.isNotEmpty(placeName)) {
//            rquery.addCriteria(Criteria.where("student.placeCode").in(placeCodeLike(examCode, placeName)));
//        }
//        rquery.addCriteria(Criteria.where("isAbsent").is(false));
//        long realCount = mongoTemplate.count(rquery, ExamStudentAnswer.class);
        long realCount = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(examCode, null, batchId, Objects.nonNull(placeCode) ? new HashSet<>(Arrays.asList(placeCode)) : placeCodeLike(examCode, placeName), roomCode, false, null, null, placeName);
        result.put("real", realCount);
        return result;
    }

    @Override
    public Map<String, List<ExamStudenDetailDto>> exportKwHzDetails(String examCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        List<ExamStudentAnswer> list = this.mongoTemplate.find(query, ExamStudentAnswer.class);
        IPage<Map> examstudentAnswerIpage = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(0, 1000000), examCode, null, null, null, null, null, null, null, null);
        Map<String, List<ExamStudenDetailDto>> result = new HashMap<String, List<ExamStudenDetailDto>>();
        result.put("isAbort", new ArrayList<ExamStudenDetailDto>());
        result.put("isCheat", new ArrayList<ExamStudenDetailDto>());
        result.put("isRepeat", new ArrayList<ExamStudenDetailDto>());
        result.put("isAbsent", new ArrayList<ExamStudenDetailDto>());
        for (Map answer : examstudentAnswerIpage.getRecords()) {
            Boolean abort = Objects.nonNull(answer.get("isAbort")) ? (Integer) answer.get("isAbort") == 1 ? true : false : null;
            Boolean absent = Objects.nonNull(answer.get("isAbsent")) ? (Integer) answer.get("isAbsent") == 1 ? true : false : null;
            Boolean cheat = Objects.nonNull(answer.get("isCheat")) ? (Integer) answer.get("isCheat") == 1 ? true : false : null;
            if (abort) {
                result.get("isAbort").add(convert(answer));
            }
            if (absent) {
                result.get("isAbsent").add(convert(answer));
            }
            if (cheat) {
                result.get("isCheat").add(convert(answer));
            }
        }
        //导出重考信息
//        query.with(new Sort(Direction.ASC, "ticketNo"));
//        List<ExamRepeatRecord> reExamList = mongoTemplate.find(query, ExamRepeatRecord.class);
        QueryWrapper<ExamRepeatRecord> examRepeatRecordQueryWrapper = new QueryWrapper<>();
        examRepeatRecordQueryWrapper.lambda().eq(ExamRepeatRecord::getExamCode, examCode)
                .orderByAsc(ExamRepeatRecord::getTicketNo);
        List<ExamRepeatRecord> reExamList = jkExamRepeatRecordService.list(examRepeatRecordQueryWrapper);
        for (ExamRepeatRecord record : reExamList) {
            result.get("isRepeat").add(convert(record));
        }
        return result;
    }

    protected ExamStudenDetailDto convert(ExamRepeatRecord examRepeatRecord) {
        ExamStudenDetailDto detailDto = new ExamStudenDetailDto();
        detailDto.setBatchId(examRepeatRecord.getBatchId());
        detailDto.setBatchName(examRepeatRecord.getBatchName());
        detailDto.setStageId(examRepeatRecord.getStageId());
        detailDto.setName(examRepeatRecord.getStudentName());
        detailDto.setPlaceCode(examRepeatRecord.getPlaceCode());
        detailDto.setRoomCode(examRepeatRecord.getRoomCode());
        detailDto.setCourseName(examRepeatRecord.getCourseName());
        detailDto.setCourseCode(examRepeatRecord.getCourseCode());
        detailDto.setTicketNo(examRepeatRecord.getTicketNo());
        detailDto.setNewBatchId(examRepeatRecord.getNewBatchId());
        detailDto.setNewBatchName(examRepeatRecord.getNewBatchName());
        detailDto.setNewStageId(examRepeatRecord.getNewStageId());
        detailDto.setRemark(examRepeatRecord.getReason());
        detailDto.setTime(examRepeatRecord.getTime());
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examRepeatRecord.getExamCode()));
//        query.addCriteria(Criteria.where("placeCode").is(examRepeatRecord.getPlaceCode()));
//        query.addCriteria(Criteria.where("roomCode").is(examRepeatRecord.getRoomCode()));
//        List<ExamRoom> list = mongoTemplate.find(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, examRepeatRecord.getExamCode())
                .eq(ExamRoom::getPlaceCode, examRepeatRecord.getPlaceCode())
                .eq(ExamRoom::getRoomCode, examRepeatRecord.getRoomCode());
        List<ExamRoom> list = jkExamRoomService.list(examRoomQueryWrapper);
        if (list.size() > 0) {
            detailDto.setPlaceName(list.get(0).getPlaceName());
            detailDto.setRoomName(list.get(0).getRoomName());
        }
        return detailDto;
    }

    protected ExamStudenDetailDto convert(Map answer) {
        ExamStudenDetailDto detailDto = new ExamStudenDetailDto();
        detailDto.setId((Long) answer.get("studentId"));
        detailDto.setBatchId((String) answer.get("batchId"));
        detailDto.setBatchName((String) answer.get("batchName"));
        detailDto.setStageId((String) answer.get("stageId"));
        detailDto.setName((String) answer.get("name"));
        detailDto.setPlaceCode((String) answer.get("placeCode"));
        detailDto.setRoomCode((String) answer.get("roomCode"));
        detailDto.setCourseName((String) answer.get("courseName"));
        detailDto.setCourseCode((String) answer.get("courseCode"));
        detailDto.setTicketNo((String) answer.get("ticketNo"));
        Boolean abort = Objects.nonNull(answer.get("isAbort")) ? (Integer) answer.get("isAbort") == 1 ? true : false : null;
        Boolean absent = Objects.nonNull(answer.get("isAbsent")) ? (Integer) answer.get("isAbsent") == 1 ? true : false : null;
        Boolean cheat = Objects.nonNull(answer.get("isCheat")) ? (Integer) answer.get("isCheat") == 1 ? true : false : null;
        Long examStudentAnswerId = (Long) answer.get("id");
        if (abort) {
            QueryWrapper<ExamAbort> examAbortQueryWrapper = new QueryWrapper<>();
            examAbortQueryWrapper.lambda().eq(ExamAbort::getExamStudentAnswerId, examStudentAnswerId);
            detailDto.getAborts().addAll(jkExamAbortService.list(examAbortQueryWrapper));
        }
        if (absent) {
            QueryWrapper<ExamAbsent> examAbsentQueryWrapper = new QueryWrapper<>();
            examAbsentQueryWrapper.lambda().eq(ExamAbsent::getExamStudentAnswerId, examStudentAnswerId);
            List<ExamAbsent> examAbsentList = jkExamAbsentService.list(examAbsentQueryWrapper);
            if (!CollectionUtils.isEmpty(examAbsentList)) {
                detailDto.setRemark(examAbsentList.get(0).getRemark());
            }
        }
        if (cheat) {
            QueryWrapper<ExamCheat> examCheatQueryWrapper = new QueryWrapper<>();
            examCheatQueryWrapper.lambda().eq(ExamCheat::getExamStudentAnswerId, examStudentAnswerId);
            List<ExamCheat> examCheatList = jkExamCheatService.list(examCheatQueryWrapper);
            if (!CollectionUtils.isEmpty(examCheatList)) {
                detailDto.setRemark(examCheatList.get(0).getReason());
                detailDto.setTime(examCheatList.get(0).getOperateTime());
                detailDto.setExamCheat(examCheatList.get(0));
            }
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(answer.getExamCode()));
//        query.addCriteria(Criteria.where("placeCode").is(answer.getStudent().getPlaceCode()));
//        query.addCriteria(Criteria.where("roomCode").is(answer.getStudent().getRoomCode()));
//        List<ExamRoom> list = mongoTemplate.find(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, (String) answer.get("examCode"))
                .eq(ExamRoom::getPlaceCode, (String) answer.get("placeCode"))
                .eq(ExamRoom::getRoomCode, (String) answer.get("roomCode"));
        List<ExamRoom> list = jkExamRoomService.list(examRoomQueryWrapper);
        if (list.size() > 0) {
            detailDto.setPlaceName(list.get(0).getPlaceName());
            detailDto.setRoomName(list.get(0).getRoomName());
        }
        return detailDto;
    }

    @Override
    public List<ExamStudentCountDto> exportStatisticKwHZ(String examCode) {
        List<ExamStudentCountDto> resultList = new ArrayList<ExamStudentCountDto>();
//        Sort.Order order1 = new Sort.Order(Direction.ASC, "batchId");
//        Sort.Order order2 = new Sort.Order(Direction.ASC, "stageId");
//        Sort sort = new Sort(order1, order2);
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
        long skip = 0;
        long limit = 10000;
        boolean over = false;
        while (!over) {
//            Aggregation agg = Aggregation.newAggregation(ExamStudent.class,
//                    Aggregation.match(Criteria.where("examCode").is(examCode)),
//                    Aggregation.group("batchId", "batchName", "stageId").count().as("fullStudentNum"),
//                    Aggregation.sort(sort),
//                    Aggregation.project("batchId", "batchName", "stageId", "fullStudentNum"),
//                    Aggregation.skip(skip),
//                    Aggregation.limit(limit)
//            ).withOptions(aggregationOptions);
//            AggregationResults<DBObject> result = mongoTemplate.aggregate(agg, ExamStudent.class,
//                    DBObject.class);
//            List<DBObject> fullStudentList = result.getMappedResults();
//            if (fullStudentList.size() < limit) {
//                over = true;
//            }
//            for (DBObject countDto : fullStudentList) {
            IPage<Map> examStudentIpage = examStudentDao.findByExamCodeAndBatchIdAndPlaceCodeAndRoomCodeAndPlaceNameByIpage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit), examCode, null, null, null, null);
            if (!CollectionUtils.isEmpty(examStudentIpage.getRecords())) {
                for (Map countDto : examStudentIpage.getRecords()) {
                    ExamStudentCountDto examStudentCountDto = new ExamStudentCountDto();
                    String stageId = (String) countDto.get("stageId");
                    String batchId = (String) countDto.get("batchId");
                    String placeCode = (String) countDto.get("placeCode");
                    String roomCode = (String) countDto.get("roomCode");
                    String batchName = (String) countDto.get("batchName");
                    long totalNum = Long.parseLong(String.valueOf(countDto.get("fullStudentNum")));
                    examStudentCountDto.setStageId(stageId);
                    examStudentCountDto.setBatchId(batchId);
                    examStudentCountDto.setPlaceCode(placeCode);
                    examStudentCountDto.setRoomCode(roomCode);
                    examStudentCountDto.setBatchName(batchName);
                    resultList.add(examStudentCountDto);
                    // 计算当前批次、当前考次下面的缺考人数
                    examStudentCountDto.setFullStudentNum(totalNum);
//                Query query = new Query();
//                query.addCriteria(Criteria.where("examCode").is(examCode));
//                query.addCriteria(Criteria.where("student.stageId").is(stageId));
//                query.addCriteria(Criteria.where("student.batchId").is(batchId));
//                query.addCriteria(Criteria.where("isAbsent").is(true));
//                long absentStudentNum = mongoTemplate.count(query, ExamStudentAnswer.class);
                    long absentStudentNum = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(examCode, stageId, batchId, null, null, true, null, null, null);
                    examStudentCountDto.setAbsentStudentNum(absentStudentNum);
                    // 计算当前批次、当前考次下面的实考人数
//                Query rquery = new Query();
//                rquery.addCriteria(Criteria.where("examCode").is(examCode));
//                rquery.addCriteria(Criteria.where("student.stageId").is(stageId));
//                rquery.addCriteria(Criteria.where("student.batchId").is(batchId));
//                rquery.addCriteria(Criteria.where("isAbsent").is(false));
//                long realStudentNum = mongoTemplate.count(rquery, ExamStudentAnswer.class);
                    long realStudentNum = examStudentAnswerDao.findByExamCodeAndStageIdAndBatchIdAndPlaceCodeAndRoomCodeAndAbsentAndCheatAndAbortAndPlaceNameCount(examCode, stageId, batchId, null, null, false, null, null, null);
                    examStudentCountDto.setRealityStudentNum(realStudentNum);
                    if (examStudentIpage.getRecords().size() < limit) {
                        over = true;
                    }
                }
            } else {
                over = true;
            }
//            }
            skip = skip + limit;
        }
        return resultList;
    }

}
