package com.qmth.jkserver.core.kw.plugin;

import cn.hutool.core.date.DateUtil;
import com.qmth.jkserver.common.Constants;
import com.qmth.jkserver.common.FileData;
import com.qmth.jkserver.common.UnZipUtils;
import com.qmth.jkserver.constant.SpringContextHolder;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.core.kw.IKwTempDataGenerator;
import com.qmth.jkserver.enums.ExamType;
import com.qmth.jkserver.model.Attachment;
import com.qmth.jkserver.model.ExamStageTemp;
import com.qmth.jkserver.model.ExamStudentTemp;
import com.qmth.jkserver.service.AttachmentService;
import com.qmth.jkserver.service.JkExamPlanService;
import com.qmth.jkserver.service.JkExamStudentTempService;
import com.qmth.jkserver.util.FileStoreUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.zip.ZipException;

/**
 * 考生临时数据
 *
 * @author tianjun
 */
public class StudentTempDataGenerator implements IKwTempDataGenerator {

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

    @Override
    public void execute(String examCode, ExamType examType, Long attachmentId) throws Exception {
        JkExamPlanService examPlanService = SpringContextHolder.getBean(JkExamPlanService.class);
        AttachmentService attachmentService = SpringContextHolder.getBean(AttachmentService.class);
        //2020-12-19日加入阿里云下载
        FileStoreUtil fileStoreConfig = SpringContextHolder.getBean(FileStoreUtil.class);
        Attachment attachment = attachmentService.findByIdService(attachmentId);
        File file = null;
        if (fileStoreConfig.workIsOss()) {
            StringJoiner stringJoiner = new StringJoiner("").add(fileStoreConfig.getWorkRoot())
                    .add(File.separator).add(attachment.getAccessUri());
            file = fileStoreConfig.ossDownload(stringJoiner.toString().replaceAll("\\\\", "/"), fileStoreConfig.getWorkRoot() + File.separator + attachment.getAccessUri(), fileStoreConfig.getWorkRoot());
        } else {
            file = new File(new File(fileStoreConfig.getWorkRoot()), attachment.getAccessUri());
        }
        switch (examType) {
            case NORMAL:
                processNormal(examCode, file, attachmentId, examPlanService, attachment.getPath());
                break;
            case UTEST:
                processUtest(examCode, file, attachmentId, examPlanService, attachment.getPath());
                break;
            case SOLFEGE:
                processSolfege(examCode, file, attachmentId, examPlanService, attachment.getPath());
                break;
            default:
                break;
        }
    }

    /**
     * 通用机考考生临时数据的生成方式
     *
     * @throws IOException
     * @throws ZipException
     * @throws ParseException
     */
    protected void processNormal(String examCode, File saveFile, Long attachmentId, JkExamPlanService examPlanService, String path) throws Exception {
        //解压文件
        List<File> kwPackage = UnZipUtils.doUnZip(saveFile, saveFile.getParentFile(), path);
        File studentFile = null;
        File batchFile = null;
        for (File f : kwPackage) {
            if (f.getName().equals(Constants.KW_BATCH_FILE_NAME)) {
                batchFile = f;
            }
            if (f.getName().equals(Constants.KW_STUDENT_FILE_NAME)) {
                studentFile = f;
            }
        }
        if (studentFile == null) {
            throw new JkServerException("zip包中没有student.csv文件");
        }
        if (batchFile == null) {
            throw new JkServerException("zip包中没有batch.csv文件");
        }
        // 存储batch stage temp
        FileData fileData = new FileData(batchFile.getAbsolutePath(), ",");
        List<ExamStageTemp> examStageTemps = new LinkedList<ExamStageTemp>();
        Map<String, String> batchId2Name = new LinkedHashMap<>();
        while (fileData.nextLine()) {
            String[] datas = fileData.getDatas();
            ExamStageTemp examStageTemp = new ExamStageTemp();
            examStageTemp.setId(SystemConstant.getDbUuid());
            examStageTemp.setExamCode(examCode);
            examStageTemp.setAttachmentId(attachmentId);
            examStageTemp.setBatchId(StringUtils.trimToNull(datas[0]));
            examStageTemp.setBatchName(StringUtils.trimToNull(datas[1]));
            batchId2Name.put(examStageTemp.getBatchId(), examStageTemp.getBatchName());
            examStageTemp.setBatchStartTime(
                    formatDate(StringUtils.trimToNull(datas[2])).getTime());
            examStageTemp.setBatchEndTime(
                    formatDate(StringUtils.trimToNull(datas[3])).getTime());
            examStageTemp.setStageId(StringUtils.trimToNull(datas[4]));
            examStageTemp.setStageStartTime(
                    formatDate(StringUtils.trimToNull(datas[5])).getTime());
            examStageTemp.setStageEndTime(
                    formatDate(StringUtils.trimToNull(datas[6])).getTime());
//            examStageTemp.setBatchStartTime(DateUtil.parse(StringUtils.trimToNull(datas[2]), SystemConstant.DEFAULT_PARSE_DATE_PATTERN).getTime());
//            examStageTemp.setBatchEndTime(DateUtil.parse(StringUtils.trimToNull(datas[3]), SystemConstant.DEFAULT_PARSE_DATE_PATTERN).getTime());
            examStageTemp.setStageId(StringUtils.trimToNull(datas[4]));
//            examStageTemp.setStageStartTime(
//                    Long.parseLong(StringUtils.trimToNull(datas[5])));
//            examStageTemp.setStageEndTime(
//                    Long.parseLong(StringUtils.trimToNull(datas[6])));
            examStageTemp.setLateLoginTime(StringUtils.trimToNull(datas[7]));
            examStageTemp.setFrozenTime(StringUtils.trimToNull(datas[8]));
            examStageTemp.setExamCode(StringUtils.trimToNull(examCode));
            examStageTemp.setAttachmentId(attachmentId);
            if (datas.length > 9) {
                examStageTemp.setSdsk(datas[9]);
            }
            examStageTemps.add(examStageTemp);
        }
        fileData.close();
        examPlanService.saveKwStageTemp(examStageTemps);
        // 存储student temp
        List<ExamStudentTemp> temps = new LinkedList<ExamStudentTemp>();
        FileData studentFileData = new FileData(studentFile.getAbsolutePath(), ",");
        while (studentFileData.nextLine()) {
            String[] datas = studentFileData.getDatas();
            ExamStudentTemp temp = new ExamStudentTemp();
            temp.setId(SystemConstant.getDbUuid());
            temp.setExamCode(examCode);
            temp.setAttachmentId(attachmentId);
            temp.setBatchId(StringUtils.trimToNull(datas[0]));
            temp.setStageId(StringUtils.trimToNull(datas[1]));
            if (StringUtils.isNotEmpty(temp.getBatchId())) {
                if (StringUtils.isEmpty(batchId2Name.get(temp.getBatchId()))) {
                    throw new JkServerException("student.csv表中的批次ID:" + temp.getBatchId() + "在batch.csv表中不存在");
                } else {
                    temp.setBatchName(batchId2Name.get(temp.getBatchId()));
                }
            }
            temp.setPlaceCode(StringUtils.trimToNull(datas[2]));
            temp.setRoomCode(StringUtils.trimToNull(datas[3]));
            temp.setTicketNo(StringUtils.trimToNull(datas[4]));
            temp.setIdcard(StringUtils.trimToNull(datas[5]));
            temp.setName(StringUtils.trimToNull(datas[6]));
            temp.setCourseCode(StringUtils.trimToNull(datas[7]));
            temp.setCourseName(StringUtils.trimToNull(datas[8]));
            temp.setExamCode(examCode);
            temp.setAttachmentId(attachmentId);
            temp.setCreateTime(System.currentTimeMillis());
            temps.add(temp);
        }
        //每一次保存10000条
        studentFileData.close();
        if (temps.size() <= 10000) {
            batchSaveKWStudentTemp(temps);
        } else {
            int n = temps.size() / 10000;
            for (int i = 0; i < n; i++) {
                List<ExamStudentTemp> subList = temps.subList(0, 10000);
                batchSaveKWStudentTemp(subList);
                temps.subList(0, 10000).clear();//从数组中剔除
            }
            if (temps.size() > 0) {//最后剩下的数据
                batchSaveKWStudentTemp(temps);
            }
        }
    }

    protected void batchSaveKWStudentTemp(List<ExamStudentTemp> examStudentTemps) {
        if (examStudentTemps == null || examStudentTemps.size() == 0) {
            return;
        }
//        MongoTemplate mongoTemplate = BeanFactory.getBean(MongoTemplate.class);
//        List<DBObject> list = new ArrayList<DBObject>();
//        for (ExamStudentTemp answer : examStudentTemps) {
//            Object object = mongoTemplate.getConverter().convertToMongoType(answer);
//            DBObject dbObject = (DBObject) JSON.parse(object.toString());
//            dbObject.put("_class", ExamStudentTemp.class.getName());
//            list.add(dbObject);
//        }
        long time1 = System.currentTimeMillis();
//        mongoTemplate.getCollection("jk_exam_student_temp").insert(list);
        JkExamStudentTempService jkExamStudentTempService = SpringContextHolder.getBean(JkExamStudentTempService.class);
        jkExamStudentTempService.saveOrUpdateBatch(examStudentTemps);
        long time2 = System.currentTimeMillis();
        LOGGER.info("----insert jk_exam_student_temp, size:" + examStudentTemps.size() + ",use time:" + ((time2 - time1) / 1000) + "(s)");
    }

    /**
     * 优特机考考生临时数据的生成方式
     *
     * @throws ParseException
     * @throws IOException
     * @throws ZipException
     */
    protected void processUtest(String examCode, File file, Long attachmentId, JkExamPlanService examPlanService, String path) throws Exception {
        processNormal(examCode, file, attachmentId, examPlanService, path);
    }

    /**
     * 视唱机考考生临时数据的生成方式
     *
     * @throws IOException
     * @throws ParseException
     */
    protected void processSolfege(String examCode, File saveFile, Long attachmentId, JkExamPlanService examPlanService, String path) throws Exception {
        this.processNormal(examCode, saveFile, attachmentId, examPlanService, path);
    }

    public static Date formatDate(String dateStr) throws ParseException {
        HashMap<String, String> dateRegFormat = new HashMap<String, String>();
        dateRegFormat.put("(\\d){1,4}-(\\d){1,2}-(\\d){1,2}\\s(\\d){1,2}:(\\d){1,2}:(\\d){1,2}",
                "yyyy-MM-dd HH:mm:ss");
        dateRegFormat.put("(\\d){1,4}/(\\d){1,2}/(\\d){1,2}\\s(\\d){1,2}:(\\d){1,2}:(\\d){1,2}", "yyyy/MM/dd HH:mm:ss");
        for (String key : dateRegFormat.keySet()) {
            if (Pattern.compile(key).matcher(dateStr).matches()) {
                DateFormat formatter2 = new SimpleDateFormat(dateRegFormat.get(key));
                return formatter2.parse(dateStr);
            }
        }
        throw new RuntimeException("不支持的时间日期格式:" + dateStr);
    }

}
