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.google.gson.reflect.TypeToken;
import com.qmth.jkserver.constant.SpringContextHolder;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dao.*;
import com.qmth.jkserver.dto.ExamKwProgressDto;
import com.qmth.jkserver.dto.KWObjectDto;
import com.qmth.jkserver.enums.ExamKwProgressType;
import com.qmth.jkserver.enums.ExamType;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.params.ExamKwProgressParams;
import com.qmth.jkserver.params.ExamPaperUncoilingParams;
import com.qmth.jkserver.service.*;
import com.qmth.jkserver.util.FileStoreUtil;
import com.qmth.jkserver.util.GsonUtil;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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 javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * 考务操作接口
 *
 * @author tianjun
 */
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class KWServiceImpl extends ServiceImpl<KwFileDao, KwFile> implements KWService {

    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(KWServiceImpl.class);

    @Resource
    private ExamRoomDao examRoomDao;

    @Resource
    private ExamRoomAddressDao examRoomAddressDao;

    @Resource
    private ExamStageDao examStageDao;

    @Resource
    private KwFileDao kwFileDao;

//    @Autowired
//    private MongoOperations mongoTemplate;

    @Resource
    @Lazy
    private JkExamPlanService examPlanService;

    @Resource
    private FileStoreUtil fileStoreConfig;

    @Resource
    private ExamRoomAddressTempDao examRoomAddressTempDao;

    @Resource
    private StudentInfoTempDao studentInfoTempDao;

    @Resource
    private StudentInfoDao studentInfoDao;

    @Resource
    @Lazy
    KWService kwService;

    @Resource
    JkExamRoomService jkExamRoomService;

    @Resource
    JkExamStageService jkExamStageService;

    @Resource
    ExamStudentService examStudentService;

    @Resource
    ExamStudentAdditionalService examStudentAdditionalService;

    @Resource
    JkExamKwProgressService jkExamKwProgressService;

    @Resource
    JkPaperUncoilingService jkPaperUncoilingService;

    @Resource
    AttachmentService attachmentService;

    @Resource
    JkExamRoomAddressTempService jkExamRoomAddressTempService;

    @Resource
    JkStudentInfoTempService jkStudentInfoTempService;

    @Resource
    JkExamRoomAddressService jkExamRoomAddressService;

    @Resource
    JkStudentInfoService jkStudentInfoService;

    @Override
    public void saveKwObejct(KWObjectDto kwObjectDto) {
        if (kwObjectDto == null) {
            throw new JkServerException("kwObject is null value");
        }
        if (kwObjectDto.getExamType() == null) {
            throw new JkServerException("kwObject examType is null value");
        }
        if (StringUtils.isEmpty(kwObjectDto.getExamCode())) {
            throw new JkServerException("kwObject examCode is null value");
        }
        KwFile kwFile = kwObjectDto.getKwFile();
        if (kwFile != null) {
            kwFile.setCreateTime(System.currentTimeMillis());
            kwFileDao.deleteByExamCode(kwObjectDto.getExamCode());
//            kwFileDao.save(kwFile);
            kwService.saveOrUpdate(kwFile);
        }
        if (kwObjectDto.getRooms() != null && kwObjectDto.getRooms().size() > 0) {
            examRoomDao.deleteByExamCode(kwObjectDto.getExamCode());
//            examRoomDao.save(kwObjectDto.getRooms());
            jkExamRoomService.saveOrUpdateBatch(kwObjectDto.getRooms());
        }
        if (kwObjectDto.getStages() != null && kwObjectDto.getStages().size() > 0) {
            examStageDao.deleteByExamCode(kwObjectDto.getExamCode());
//            examStageDao.save(kwObjectDto.getStages());
            jkExamStageService.saveOrUpdateBatch(kwObjectDto.getStages());
        }
        //存储考生数据

        if (kwFile.getStudentFileTempId() != null) {
            delStudentByExamCode(kwObjectDto.getExamCode());
            int skip = 0;
            int limit = 10000;
            boolean isend = false;
            while (!isend) {
                List<ExamStudentTemp> temps = examPlanService.findKwStudentTemp(kwObjectDto.getExamCode(),
                        kwFile.getStudentFileTempId(), skip, limit);
                if (temps.size() < limit) {
                    isend = true;
                }
                saveStudent(temps);
                skip = skip + limit;
            }
        }
        //存储考生附加数据
        if (kwFile.getStudentAdditionalFileTempId() != null && kwObjectDto.getExamType().equals(ExamType.UTEST)) {
            delStudentAdditionalByExamCode(kwObjectDto.getExamCode());
            int skip = 0;
            int limit = 10000;
            boolean isend = false;
            while (!isend) {
                List<ExamStudentAdditionalTemp> temps = examPlanService.findKwStudentAdditionalTemp(kwObjectDto.getExamCode(),
                        kwFile.getStudentAdditionalFileTempId(), skip, limit);
                if (temps.size() < limit) {
                    isend = true;
                }
                saveStudentAdditiona(temps);
                skip = skip + limit;
            }
        }
    }

    private void delStudentByExamCode(String examCode) {
//        DBObject delObject = new BasicDBObject("exam_code", examCode);
//        mongoTemplate.getCollection("jk_exam_student").remove(delObject);
        QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
        examStudentQueryWrapper.lambda().eq(ExamStudent::getExamCode, examCode);
        examStudentService.remove(examStudentQueryWrapper);
    }

    private void delStudentAdditionalByExamCode(String examCode) {
//        DBObject delObject = new BasicDBObject("exam_code", examCode);
//        mongoTemplate.getCollection("jk_exam_student_additional").remove(delObject);
        QueryWrapper<ExamStudentAdditional> examStudentAdditionalQueryWrapper = new QueryWrapper<>();
        examStudentAdditionalQueryWrapper.lambda().eq(ExamStudentAdditional::getExamCode, examCode);
        examStudentAdditionalService.remove(examStudentAdditionalQueryWrapper);
    }

    private void saveStudent(List<ExamStudentTemp> examStudents) {
        if (examStudents == null || examStudents.size() == 0) {
            return;
        }
//        for (ExamStudentTemp examStudentTemp : examStudents) {
//            examStudentTemp.removeField("_id");
//            examStudentTemp.removeField("attachment_id");
//            examStudentTemp.removeField("_class");
//            examStudentTemp.put("_class", ExamStudent.class.getName());
//        }
//        mongoTemplate.getCollection("jk_exam_student").insert(examStudents);
        List<ExamStudent> examStudentList = GsonUtil.fromJson(GsonUtil.toJson(examStudents), new TypeToken<List<ExamStudent>>() {
        }.getType());
        examStudentService.saveOrUpdateBatch(examStudentList);
    }

    private void saveStudentAdditiona(List<ExamStudentAdditionalTemp> examStudentAdditionals) {
        if (examStudentAdditionals == null || examStudentAdditionals.size() == 0) {
            return;
        }
//        for (DBObject dbObject : examStudentAdditionals) {
//            dbObject.removeField("_id");
//            dbObject.removeField("attachment_id");
//            dbObject.removeField("_class");
//            dbObject.put("_class", ExamStudentAdditional.class.getName());
//        }
//        mongoTemplate.getCollection("jk_exam_student_additional").insert(examStudentAdditionals);
        List<ExamStudentAdditional> examStudentAdditionalList = GsonUtil.fromJson(GsonUtil.toJson(examStudentAdditionals), new TypeToken<List<ExamStudentAdditional>>() {
        }.getType());
        examStudentAdditionalService.saveOrUpdateBatch(examStudentAdditionalList);
    }

//	/**
//	 * 如果数据量过大 建议不要使用此方法
//	 */
//	@Override
//	public KWObjectDto findKwObjectByExamCode(String examCode) {
//		//获取kwfile
//		KwFile kwFile = findKwFileByExamCode(examCode);
//		//获取stage
//		List<ExamStage> stages = examStageDao.findByExamCode(examCode);
//		//获取rooms
//		Query roomQuery = new Query();
//		roomQuery.addCriteria(Criteria.where("examCode").is(examCode));
//		List<ExamRoom> rooms = mongoTemplate.find(roomQuery, ExamRoom.class);
//		//获取students
//		Query studentQuery = new Query();
//		studentQuery.addCriteria(Criteria.where("examCode").is(examCode));
//		List<ExamStudent> students = mongoTemplate.find(studentQuery, ExamStudent.class);
//		//获取考生附加信息
//		Query additionQuery = new Query();
//		additionQuery.addCriteria(Criteria.where("examCode").is(examCode));
//		List<ExamStudentAdditional> additionals = mongoTemplate.find(additionQuery, ExamStudentAdditional.class);
//		KWObjectDto kwObjectDto = new KWObjectDto();
//		kwObjectDto.setKwFile(kwFile);
//		kwObjectDto.setExamCode(examCode);
//		kwObjectDto.setRooms(rooms);
//		kwObjectDto.setStages(stages);
//		kwObjectDto.setStudents(students);
//		kwObjectDto.setAdditionals(additionals);
//		return kwObjectDto;
//	}

    @Override
    public KwFile findKwFileByExamCode(String examCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        KwFile kwFile = mongoTemplate.findOne(query, KwFile.class);
        QueryWrapper<KwFile> kwFileQueryWrapper = new QueryWrapper<>();
        kwFileQueryWrapper.lambda().eq(KwFile::getExamCode, examCode);
        return kwService.getOne(kwFileQueryWrapper);
    }

    @Override
    public ExamKwProgress saveKwProgress(ExamKwProgress examKwProgress) {
        if (examKwProgress.getType() == null) {
            throw JkServerException.withFieldValidateError("参数type不能够为空");
        }
        if (StringUtils.isEmpty(examKwProgress.getExamCode())) {
            throw JkServerException.withFieldValidateError("参数examCode不能够为空");
        }
        if (StringUtils.isEmpty(examKwProgress.getPlaceCode())) {
            throw JkServerException.withFieldValidateError("参数placeCode不能够为空");
        }
        if (StringUtils.isEmpty(examKwProgress.getRoomCode())) {
            throw JkServerException.withFieldValidateError("参数roomCode不能够为空");
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examKwProgress.getExamCode()));
//        query.addCriteria(Criteria.where("placeCode").is(examKwProgress.getPlaceCode()));
//        query.addCriteria(Criteria.where("roomCode").is(examKwProgress.getRoomCode()));
//        query.addCriteria(Criteria.where("type").is(examKwProgress.getType()));
//        List<ExamKwProgress> examKwProgresses = mongoTemplate.find(query, ExamKwProgress.class);
        QueryWrapper<ExamKwProgress> examKwProgressQueryWrapper = new QueryWrapper<>();
        examKwProgressQueryWrapper.lambda().eq(ExamKwProgress::getExamCode, examKwProgress.getExamCode())
                .eq(ExamKwProgress::getPlaceCode, examKwProgress.getPlaceCode())
                .eq(ExamKwProgress::getRoomCode, examKwProgress.getRoomCode())
                .eq(ExamKwProgress::getType, examKwProgress.getType());
        List<ExamKwProgress> examKwProgresses = jkExamKwProgressService.list(examKwProgressQueryWrapper);
        examPlanService.updateRoomKwAlready(examKwProgress.getExamCode(),
                examKwProgress.getPlaceCode(), examKwProgress.getRoomCode(),
                examKwProgress.getType());
        if (examKwProgresses.size() == 0) {
            examKwProgress.setDownload(true);
            examKwProgress.setTime(System.currentTimeMillis());
//            examKwProgressDao.save(examKwProgress);
            jkExamKwProgressService.saveOrUpdate(examKwProgress);
            return examKwProgress;
        } else {
            examKwProgresses.get(0).setDownload(true);
            examKwProgresses.get(0).setTime(System.currentTimeMillis());
//            examKwProgressDao.save(examKwProgresses.get(0));
            jkExamKwProgressService.saveOrUpdate(examKwProgresses.get(0));
            return examKwProgresses.get(0);
        }
    }

    @Override
    public ExamPaperUncoiling getPaperPassword(String examCode, String batchId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("batchId").is(batchId));
//        List<ExamPaperUncoiling> paperUncoilings = mongoTemplate.find(query, ExamPaperUncoiling.class);
        QueryWrapper<ExamPaperUncoiling> examPaperUncoilingQueryWrapper = new QueryWrapper<>();
        examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getExamCode, examCode)
                .eq(ExamPaperUncoiling::getBatchId, batchId);
        List<ExamPaperUncoiling> paperUncoilings = jkPaperUncoilingService.list(examPaperUncoilingQueryWrapper);
        return paperUncoilings.size() > 0 ? paperUncoilings.get(0) : null;
    }

    @Override
    public List<ExamPaperUncoiling> queryExamPaperUncoiling(ExamPaperUncoilingParams params) {
        List<ExamPaperUncoiling> list = new ArrayList<ExamPaperUncoiling>();
        List<Map<String, Object>> maps = examPlanService.distinctBatch(params.getExamCode());
        for (Map<String, Object> map : maps) {
            String batchId = (String) map.get("value");
            String batchName = (String) map.get("name");
//            Query query = new Query();
            QueryWrapper<ExamPaperUncoiling> examPaperUncoilingQueryWrapper = new QueryWrapper<>();
            if (StringUtils.isNotEmpty(params.getExamCode())) {
//                query.addCriteria(Criteria.where("examCode").is(params.getExamCode()));
                examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getExamCode, params.getExamCode());
            }
            if (StringUtils.isNotEmpty(batchId)) {
//                query.addCriteria(Criteria.where("batchId").is(batchId));
                examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getBatchId, batchId);
            }
//            List<ExamPaperUncoiling> rlist = mongoTemplate.find(query, ExamPaperUncoiling.class);
            List<ExamPaperUncoiling> rlist = jkPaperUncoilingService.list(examPaperUncoilingQueryWrapper);
            ExamPaperUncoiling examPaperUncoiling = new ExamPaperUncoiling();
            Long time = null;
            if (rlist.size() > 0) {
                time = rlist.get(0).getTime();
                examPaperUncoiling.setId(rlist.get(0).getId());
                examPaperUncoiling.setPassword(rlist.get(0).getPassword());
            }
            examPaperUncoiling.setExamCode(params.getExamCode());
            examPaperUncoiling.setBatchId(batchId);
            examPaperUncoiling.setBatchName(batchName);
            examPaperUncoiling.setTime(time);
            examPaperUncoiling.setBatchName(batchName);
            ExamPlan examPlan = examPlanService.findByExamCode(params.getExamCode());
            if (examPlan == null) {
                throw JkServerException.withFieldValidateError("错误的考试识别码：" + params.getExamCode());
            }
            examPaperUncoiling.setExamName(examPlan.getName());
            list.add(examPaperUncoiling);
        }
        return list;
    }

    @Override
    public String findBatchName(String examCode, String batchId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("batchId").is(batchId));
//        List<ExamStage> stages = mongoTemplate.find(query, ExamStage.class);
        QueryWrapper<ExamStage> examStageQueryWrapper = new QueryWrapper<>();
        examStageQueryWrapper.lambda().eq(ExamStage::getExamCode, examCode)
                .eq(ExamStage::getBatchId, batchId);
        List<ExamStage> stages = jkExamStageService.list(examStageQueryWrapper);
        if (stages.size() == 0) {
            throw JkServerException.withFieldValidateError("找不到批次信息，考试识别码：" + examCode + ",批次id:" + batchId);
        }
        return stages.get(0).getBatchName();
    }

    @Override
    public ExamPaperUncoiling save(ExamPaperUncoiling examPaperUncoiling) throws Exception {
        if (StringUtils.isEmpty(examPaperUncoiling.getExamCode())) {
            throw JkServerException.withFieldValidateError("考试识别码不能够为空");
        }
        if (StringUtils.isEmpty(examPaperUncoiling.getBatchId())) {
            throw JkServerException.withFieldValidateError("批次ID不能够为空");
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examPaperUncoiling.getExamCode()));
//        query.addCriteria(Criteria.where("batchId").is(examPaperUncoiling.getBatchId()));
//        List<ExamPaperUncoiling> examPaperUncoilings = mongoTemplate.find(query, ExamPaperUncoiling.class);
        QueryWrapper<ExamPaperUncoiling> examPaperUncoilingQueryWrapper = new QueryWrapper<>();
        examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getExamCode, examPaperUncoiling.getExamCode())
                .eq(ExamPaperUncoiling::getBatchId, examPaperUncoiling.getBatchId());
        List<ExamPaperUncoiling> examPaperUncoilings = jkPaperUncoilingService.list(examPaperUncoilingQueryWrapper);
        this.checkPaperFilePasswordIsRight(examPaperUncoiling.getExamCode(), examPaperUncoiling.getBatchId(), examPaperUncoiling.getPassword());
        if (examPaperUncoilings.size() > 0) {
            examPaperUncoilings.get(0).setTime(System.currentTimeMillis());
            examPaperUncoilings.get(0).setPassword(examPaperUncoiling.getPassword());
//            examPaperUncoilingDao.save(examPaperUncoilings.get(0));
            jkPaperUncoilingService.saveOrUpdate(examPaperUncoilings.get(0));
            return examPaperUncoilings.get(0);
        } else {
            examPaperUncoiling.setTime(System.currentTimeMillis());
//            examPaperUncoilingDao.save(examPaperUncoiling);
            jkPaperUncoilingService.saveOrUpdate(examPaperUncoiling);
            return examPaperUncoiling;
        }
    }

    //判断试卷的解压密码是否正确
    protected void checkPaperFilePasswordIsRight(String examCode, String batchId, String password) throws Exception {
        List<KwFile> kwFiles = kwFileDao.findByExamCode(examCode);
        if (kwFiles.size() == 0) {
            throw JkServerException.withMessage("未获取到当前考试的考务数据信息,kwFile is null");
        } else {
            KwFile kwFile = kwFiles.get(0);
//            Attachment paperTemp = kwFile.getPaperFileTemp();
            Attachment paperTemp = attachmentService.getById(kwFile.getPaperFileTempId());
            String accessUri = paperTemp.getAccessUri();
            //2020-12-19日加入阿里云下载
            String workWoot = fileStoreConfig.getWorkRoot();
            File root = new File(workWoot);
            //2020-12-19日加入阿里云下载
            File paperFile = null;
            if (fileStoreConfig.workIsOss()) {
                StringJoiner stringJoiner = new StringJoiner("").add(fileStoreConfig.getWorkRoot())
                        .add(File.separator).add(accessUri);
                paperFile = fileStoreConfig.ossDownload(stringJoiner.toString().replaceAll("\\\\", "/"), fileStoreConfig.getWorkRoot() + File.separator + accessUri, fileStoreConfig.getWorkRoot());
            } else {
                paperFile = new File(root, accessUri);
            }
            if (!paperFile.exists()) {
                throw JkServerException.withMessage("试卷临时文件不存在:" + paperFile.getAbsolutePath());
            }
            File targetPaperFileZip = new File(paperFile.getParent(), SystemConstant.getNanoId() + SystemConstant.ZIP_PREFIX);
            targetPaperFileZip.createNewFile();
            java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(paperFile);
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(paperFile));
            ZipEntry zipEntry = null;
            InputStream paperStream = null;
            try {
                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                    if (zipEntry.getName().toLowerCase().endsWith("Paper.zip".toLowerCase())) {
                        paperStream = zipFile.getInputStream(zipEntry);
                        zipInputStream.closeEntry();
                        break;
                    }
                }
                if (paperStream == null) {
                    throw JkServerException.withMessage("考试试卷包中paper.zip不存在，请检查试卷包结构是否正确");
                } else {
                    OutputStream outputStream = null;
                    java.util.zip.ZipFile batchPaper = null;
                    ZipInputStream batchPaperStream = null;
                    ZipEntry batchPaperEntry = null;
                    InputStream batchPaperInputStream = null;
                    OutputStream batchPaperOutStream = null;
                    try {
                        outputStream = new FileOutputStream(targetPaperFileZip);
                        IOUtils.copy(paperStream, outputStream);
                        batchPaper = new java.util.zip.ZipFile(targetPaperFileZip);
                        batchPaperStream = new ZipInputStream(new FileInputStream(targetPaperFileZip));
                        File targetBatchPaperFile = new File(targetPaperFileZip.getParentFile(), SystemConstant.getNanoId() + SystemConstant.ZIP_PREFIX);
                        targetBatchPaperFile.createNewFile();
                        batchPaperOutStream = new FileOutputStream(targetBatchPaperFile);
                        while ((batchPaperEntry = batchPaperStream.getNextEntry()) != null) {
                            if (batchPaperEntry.getName().endsWith("_" + batchId + SystemConstant.ZIP_PREFIX)) {
                                batchPaperInputStream = batchPaper.getInputStream(batchPaperEntry);
                                batchPaperStream.closeEntry();
                                break;
                            }
                        }
                        if (batchPaperInputStream == null) {
                            throw JkServerException.withMessage("批次ID=" + batchId + "对应的试卷包在考务试卷包中不存在");
                        }
                        IOUtils.copy(batchPaperInputStream, batchPaperOutStream);
                        unZipByPassword(targetBatchPaperFile, password);
                    } finally {
                        if (outputStream != null) {
                            IOUtils.closeQuietly(outputStream);
                        }
                        if (paperStream != null) {
                            IOUtils.closeQuietly(paperStream);
                        }
                        if (batchPaper != null) {
                            IOUtils.closeQuietly(batchPaper);
                        }
                        if (batchPaperStream != null) {
                            IOUtils.closeQuietly(batchPaperStream);
                        }
                        if (batchPaperInputStream != null) {
                            IOUtils.closeQuietly(batchPaperInputStream);
                        }
                        if (batchPaperOutStream != null) {
                            IOUtils.closeQuietly(batchPaperOutStream);
                        }
                    }
                }
            } finally {
                if (zipInputStream != null) {
                    IOUtils.closeQuietly(zipInputStream);
                }
                if (zipFile != null) {
                    IOUtils.closeQuietly(zipFile);
                }
            }
        }
    }

    protected void unZipByPassword(File file, String password) throws Exception {
        unZipCommon(file, password, file.getParentFile().getAbsolutePath());
    }

    /**
     * 解压缩zip
     *
     * @param file
     * @param password
     * @param destPath
     * @throws ZipException
     */
    protected void unZipCommon(File file, String password, String destPath) throws ZipException {
        ZipFile zFile = new ZipFile(file);  //首先创建ZipFile指向磁盘上的.zip文件
//        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
//        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.SYS_CONFIG_KEY_CHARSETS);
        zFile.setFileNameCharset(SystemConstant.CHARSET_NAME);       //设置文件名编码，在GBK系统中需要设置
        if (!zFile.isValidZipFile()) {   // 验证.zip文件是否合法，包括文件是否存在、是否为zip文件、是否被损坏等
            throw JkServerException.withMessage("压缩文件可能已被损坏.");
        }
        if (zFile.isEncrypted()) {
            zFile.setPassword(password.toCharArray());  // 设置密码
        } else {
            throw JkServerException.withMessage("试卷未加密，不需要开卷.");
        }
        zFile.extractAll(file.getParentFile().getAbsolutePath());      // 将文件抽出到解压目录(解压)
    }

    /**
     * zip解压缩
     *
     * @param file
     * @param password
     * @return
     * @throws Exception
     */
    @Override
    public List<File> unZipByPasswordByDest(File file, String password) throws Exception {
        ZipFile zFile = new ZipFile(file);  //首先创建ZipFile指向磁盘上的.zip文件
//        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
//        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.SYS_CONFIG_KEY_CHARSETS);
        zFile.setFileNameCharset(SystemConstant.CHARSET_NAME);       //设置文件名编码，在GBK系统中需要设置
        if (!zFile.isValidZipFile()) {   // 验证.zip文件是否合法，包括文件是否存在、是否为zip文件、是否被损坏等
            throw JkServerException.withMessage("压缩文件可能已被损坏.");
        }
        if (zFile.isEncrypted()) {
            zFile.setPassword(password.toCharArray());  // 设置密码
        } else {
            throw JkServerException.withMessage("试卷未加密，不需要开卷.");
        }
        String dest = file.getParentFile().getAbsolutePath() + File.separator + SystemConstant.getNanoId();
        zFile.extractAll(dest);
        File destFile = new File(dest);
        return Arrays.asList(destFile.listFiles());
    }

    @Override
    public Page<ExamKwProgressDto> queryKwProgress(ExamKwProgressParams params) {
//        Query query = new Query();
//        if (StringUtils.isNotEmpty(params.getExamCode())) {
//            query.addCriteria(Criteria.where("examCode").is(params.getExamCode()));
//        }
//        if (StringUtils.isNotEmpty(params.getPlaceCode())) {
//            query.addCriteria(Criteria.where("placeCode").is(params.getPlaceCode()));
//        }
//        if (StringUtils.isNotEmpty(params.getPlaceName())) {
//            query.addCriteria(Criteria.where("placeName").regex(params.getPlaceName()));
//        }
        Boolean kwKcAlready = null, kwPaperAlready = null, kwUncolilingAlready = null;
        if (params.getAlready() != null) {
            if (ExamKwProgressType.KW.equals(params.getType())) {
//                query.addCriteria(Criteria.where("kwAlready.kcAlready").is(params.getAlready().booleanValue()));
                kwKcAlready = params.getAlready();
            }
            if (ExamKwProgressType.PAPER.equals(params.getType())) {
//                query.addCriteria(Criteria.where("kwAlready.paperAlready").is(params.getAlready().booleanValue()));
                kwPaperAlready = params.getAlready();
            }
            if (ExamKwProgressType.UNCOILING.equals(params.getType())) {
//                query.addCriteria(Criteria.where("kwAlready.uncolilingAlready").is(params.getAlready().booleanValue()));
                kwUncolilingAlready = params.getAlready();
            }
        }
//        long count = mongoTemplate.count(query, ExamRoom.class);
//        long count = examRoomDao.listPageCount(params.getExamCode(), params.getPlaceCode(), params.getPlaceName()
//                , kwKcAlready, kwPaperAlready, kwUncolilingAlready);
//        Order order1 = new Order(Direction.ASC, "placeCode");
//        Order order2 = new Order(Direction.ASC, "roomCode");
//        Sort sort = new Sort(order1, order2);
//        query.with(sort);
//        query.skip((params.getPageNo() - 1) * params.getPageSize());
//        query.limit(params.getPageSize());
//        List<ExamRoom> examRooms = mongoTemplate.find(query, ExamRoom.class);
        IPage<ExamRoom> examRooms = examRoomDao.listPageByKw(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(params.getPageNo(), params.getPageSize()),
                params.getExamCode(), params.getPlaceCode(), params.getPlaceName()
                , kwKcAlready, kwPaperAlready, kwUncolilingAlready);
        List<ExamKwProgressDto> result = new ArrayList<>();
        for (ExamRoom examRoom : examRooms.getRecords()) {
            ExamKwProgressDto examKwProgressDto = new ExamKwProgressDto();
            examKwProgressDto.setExamCode(examRoom.getExamCode());
            examKwProgressDto.setPlaceCode(examRoom.getPlaceCode());
            examKwProgressDto.setPlaceName(examRoom.getPlaceName());
            examKwProgressDto.setRoomCode(examRoom.getRoomCode());
            examKwProgressDto.setRoomName(examRoom.getRoomName());
//            Query subquery = new Query();
//            subquery.addCriteria(Criteria.where("examCode").is(examRoom.getExamCode()));
//            subquery.addCriteria(Criteria.where("placeCode").is(examRoom.getPlaceCode()));
//            subquery.addCriteria(Criteria.where("roomCode").is(examRoom.getRoomCode()));
//            subquery.addCriteria(Criteria.where("type").is(params.getType()));
//            List<ExamKwProgress> kwProgresses = mongoTemplate.find(subquery, ExamKwProgress.class);
            QueryWrapper<ExamKwProgress> examKwProgressQueryWrapper = new QueryWrapper<>();
            examKwProgressQueryWrapper.lambda().eq(ExamKwProgress::getExamCode, examRoom.getExamCode())
                    .eq(ExamKwProgress::getPlaceCode, examRoom.getPlaceCode())
                    .eq(ExamKwProgress::getRoomCode, examRoom.getRoomCode())
                    .eq(ExamKwProgress::getType, params.getType());
            List<ExamKwProgress> kwProgresses = jkExamKwProgressService.list(examKwProgressQueryWrapper);
            if (kwProgresses.size() > 0) {
                examKwProgressDto.setTime(kwProgresses.get(0).getTime());
            }
            result.add(examKwProgressDto);
        }
        return new PageImpl<ExamKwProgressDto>(result, PageRequest.of(params.getPageNo() - 1, params.getPageSize()), examRooms.getTotal());
    }

    @Override
    public void removeExamPaperUncoiling(String examCode, String batchId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("batchId").is(batchId));
//        mongoTemplate.remove(query, ExamPaperUncoiling.class);
        QueryWrapper<ExamPaperUncoiling> examPaperUncoilingQueryWrapper = new QueryWrapper<>();
        examPaperUncoilingQueryWrapper.lambda().eq(ExamPaperUncoiling::getExamCode, examCode)
                .eq(ExamPaperUncoiling::getBatchId, batchId);
        jkPaperUncoilingService.remove(examPaperUncoilingQueryWrapper);
    }

    @Override
    public void removeExamPaperUncoiling(String id) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("id").is(new ObjectId(id)));
//        mongoTemplate.remove(query, ExamPaperUncoiling.class);
        jkPaperUncoilingService.removeById(Long.parseLong(id));
    }

    @Override
    public void saveRoomMonitorTempInfo(List<ExamRoomAddressTemp> addressTemps, List<StudentInfoTemp> studentInfos) {
        if (addressTemps.size() > 0) {
//            examRoomAddressTempDao.save(addressTemps);
            jkExamRoomAddressTempService.saveOrUpdateBatch(addressTemps);
        }
        if (studentInfos.size() > 0) {
//            studentInfoTempDao.save(studentInfos);
            jkStudentInfoTempService.saveOrUpdateBatch(studentInfos);
        }
    }

    @Override
    public void saveRoomMonitorInfo(String examCode, String attachmentId) {
        List<ExamRoomAddressTemp> examRoomAddressTemps = examRoomAddressTempDao.findByExamCodeAndAttachmentId(examCode, Long.parseLong(attachmentId));
        List<ExamRoomAddress> examRoomAddresses = new ArrayList<>();
        for (ExamRoomAddressTemp examRoomAddressTemp : examRoomAddressTemps) {
            ExamRoomAddress examRoomAddress = new ExamRoomAddress(examRoomAddressTemp);
            examRoomAddresses.add(examRoomAddress);
        }
        examRoomAddressDao.deleteByExamCode(examCode);
//        examRoomAddressDao.save(examRoomAddresses);
        jkExamRoomAddressService.saveOrUpdateBatch(examRoomAddresses);

        List<StudentInfoTemp> studentInfoTemps = studentInfoTempDao.findByExamCodeAndAttachmentId(examCode, Long.parseLong(attachmentId));
        List<StudentInfo> studentinfos = new ArrayList<>();
        for (StudentInfoTemp studentInfoTemp : studentInfoTemps) {
            StudentInfo studentInfo = new StudentInfo(studentInfoTemp);
            studentinfos.add(studentInfo);
        }
        studentInfoDao.deleteByExamCode(examCode);
//        studentInfoDao.save(studentinfos);
        jkStudentInfoService.saveOrUpdateBatch(studentinfos);
    }
}
