package com.qmth.jkserver.core.ow;

import com.qmth.jkserver.constant.SpringContextHolder;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.enums.ExamStatus;
import com.qmth.jkserver.enums.ExamType;
import com.qmth.jkserver.model.ExamPlan;
import com.qmth.jkserver.model.ExamStudent;
import com.qmth.jkserver.model.ExamStudentAnswer;
import com.qmth.jkserver.model.SysConfig;
import com.qmth.jkserver.service.CommonCacheService;
import com.qmth.jkserver.service.ExamStudentAnswerService;
import com.qmth.jkserver.service.ExamStudentService;
import com.qmth.jkserver.service.JkExamPlanService;
import com.qmth.jkserver.util.FileStoreUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 视唱OW阅卷数据导出(不包含考生答案，考生答案需要在服务器本地或者OSS中导出)
 *
 * @author tianjun
 */
public class Solfege2OWExport implements IOW2Export {

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

    @Override
    public File execute(String examCode) throws IOException {
        // 1\校验当前考试计划的状态是否符合导出的条件
        JkExamPlanService examPlanService = SpringContextHolder.getBean(JkExamPlanService.class);
        FileStoreUtil fileStoreConfig = SpringContextHolder.getBean(FileStoreUtil.class);
        ExamPlan examPlan = examPlanService.findByExamCode(examCode);
        if (examPlan == null) {
            throw JkServerException.EXAM_CODE_INVALID;
        }
        if (!ExamStatus.PUBLISHED.equals(examPlan.getExamStatus())) {
            throw JkServerException.EXAM_PLAN_UN_PUBLISHED;
        }
        if (!ExamType.SOLFEGE.equals(examPlan.getExamType())) {
            throw new JkServerException("考试类型不是视唱的考试类型");
        }
        File dir = new File(fileStoreConfig.getWorkRoot());
        dir = new File(dir,
                new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + File.separator + SystemConstant.getNanoId());
        File storedir = new File(dir, "src");
        if (!storedir.exists()) {
            storedir.mkdirs();
        }
        LOGGER.info("创建OW临时文件夹成功：", dir.getAbsolutePath());
        String time = new SimpleDateFormat("yyyyy-MM-ddHHmmss").format(new Date());
        File zipFile = new File(dir, "OW阅卷数据_" + examCode + "_" + time + SystemConstant.ZIP_PREFIX);
        zipFile.createNewFile();
        OutputStream outputStream = new FileOutputStream(zipFile);
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream, Charset.forName(SystemConstant.CHARSET_NAME));
        try {
            // 2\导出 答案路径.txt 文件
            buildAnswerPathFile(examPlan, storedir, zipOutputStream);
            // 3\导出 科目数据.txt
            buildCourseDataFile(examPlan, storedir, zipOutputStream);
            // 4\导出考生试卷表
            buildStudentPaperFile(examPlan, storedir, zipOutputStream);
        } finally {
            if (zipOutputStream != null) {
                IOUtils.closeQuietly(zipOutputStream);
            }
            if (outputStream != null) {
                IOUtils.closeQuietly(outputStream);
            }
        }
        System.out.println("build Normal2OWExport zip successfully:" + zipFile.getAbsolutePath());
        return zipFile;
    }

    protected void buildAnswerPathFile(ExamPlan examPlan, File dir, ZipOutputStream zipOutputStream)
            throws IOException {
        ExamStudentAnswerService examStudentAnswerService = SpringContextHolder.getBean(ExamStudentAnswerService.class);
        ExamStudentService examStudentService = SpringContextHolder.getBean(ExamStudentService.class);
        // 分页读取答案，每一次取出10000条,然后往文件中10000条数据
        int skip = 0;
        int limit = 10000;
        boolean over = false;
        File file = new File(dir, "答案路径.txt");
        file.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
//        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
//        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.SYS_CONFIG_KEY_CHARSETS);
        OutputStreamWriter outBatch = new OutputStreamWriter(fileOutputStream, SystemConstant.CHARSET_NAME);
        BufferedWriter bufferedWriter = new BufferedWriter(outBatch);
        try {
            while (!over) {
                List<ExamStudentAnswer> examStudentAnswers = examStudentAnswerService
                        .findRecordExistsAnswerByExamCode(examPlan.getExamCode(), skip, limit);
                if (examStudentAnswers.size() < limit) {
                    over = true;
                }
                for (ExamStudentAnswer answer : examStudentAnswers) {
                    if (answer == null || StringUtils.isEmpty(answer.getPaperName())) {
                        continue;
                    }
                    if (answer.getIsAbsent()) {
                        continue;
                    }
//					ExamStudent examStudent = answer.getStudent();
                    ExamStudent examStudent = examStudentService.getById(answer.getStudentId());
                    if (StringUtils.isEmpty(examStudent.getTicketNo())) {
                        throw new JkServerException("缺少准考证号,考生ID=" + examStudent.getId());
                    }
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(examStudent.getTicketNo()).append(",");
                    stringBuffer.append("1,1,1").append(",");
                    stringBuffer.append("item1").append("\\").append(examStudent.getTicketNo() + SystemConstant.ZIP_PREFIX);
                    stringBuffer.append(",0");
                    stringBuffer.append("\r\n");
                    bufferedWriter.write(stringBuffer.toString());
                }
                bufferedWriter.flush();
                skip = skip + limit;
            }
        } finally {
            if (bufferedWriter != null) {
                bufferedWriter.close();
            }
            if (fileOutputStream != null) {
                IOUtils.closeQuietly(fileOutputStream);
            }
        }
        InputStream inputStream = new FileInputStream(file);
        try {
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            IOUtils.copy(inputStream, zipOutputStream);
        } finally {
            if (inputStream != null) {
                IOUtils.closeQuietly(inputStream);
            }
            zipOutputStream.closeEntry();
        }
    }

    // 生成考生主观题答案文件 直接通过流提取的方式
    protected void buildCourseDataFile(ExamPlan examPlan, File dir, ZipOutputStream zipOutputStream)
            throws IOException {
        ExamStudentAnswerService examStudentAnswerService = SpringContextHolder.getBean(ExamStudentAnswerService.class);
        ExamStudentService examStudentService = SpringContextHolder.getBean(ExamStudentService.class);
        // 分页读取答案，每一次取出10000条,然后往文件中10000条数据
        int skip = 0;
        int limit = 10000;
        boolean over = false;
        File file = new File(dir, "科目数据.txt");
        file.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
//        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
//        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.SYS_CONFIG_KEY_CHARSETS);
        OutputStreamWriter outBatch = new OutputStreamWriter(fileOutputStream, SystemConstant.CHARSET_NAME);
        BufferedWriter bufferedWriter = new BufferedWriter(outBatch);
        try {
            while (!over) {
                List<ExamStudentAnswer> examStudentAnswers = examStudentAnswerService
                        .findRecordExistsAnswerByExamCode(examPlan.getExamCode(), skip, limit);
                if (examStudentAnswers.size() < limit) {
                    over = true;
                }
                for (ExamStudentAnswer answer : examStudentAnswers) {
                    if (answer == null || StringUtils.isEmpty(answer.getPaperName())) {
                        continue;
                    }
                    if (answer.getIsAbsent()) {
                        continue;
                    }
//					ExamStudent examStudent = answer.getStudent();
                    ExamStudent examStudent = examStudentService.getById(answer.getStudentId());
                    if (StringUtils.isEmpty(examStudent.getTicketNo())) {
                        throw new JkServerException("缺少准考证号,考生ID=" + examStudent.getId());
                    }
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(examStudent.getTicketNo()).append(",1");
                    stringBuffer.append("\r\n");
                    bufferedWriter.write(stringBuffer.toString());
                }
                bufferedWriter.flush();
                skip = skip + limit;
            }
        } finally {
            if (bufferedWriter != null) {
                bufferedWriter.close();
            }
            if (fileOutputStream != null) {
                IOUtils.closeQuietly(fileOutputStream);
            }
        }
        InputStream inputStream = new FileInputStream(file);
        try {
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            IOUtils.copy(inputStream, zipOutputStream);
        } finally {
            if (inputStream != null) {
                IOUtils.closeQuietly(inputStream);
            }
            zipOutputStream.closeEntry();
        }
    }

    // 增加一个描述文件 准考证号-试卷ID
    protected void buildStudentPaperFile(ExamPlan examPlan, File dir, ZipOutputStream zipOutputStream)
            throws IOException {
        ExamStudentAnswerService examStudentAnswerService = SpringContextHolder.getBean(ExamStudentAnswerService.class);
        ExamStudentService examStudentService = SpringContextHolder.getBean(ExamStudentService.class);
        // 分页读取答案，每一次取出10000条,然后往文件中10000条数据
        int skip = 0;
        int limit = 10000;
        boolean over = false;
        File file = new File(dir, "student-paper.txt");
        file.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
//        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
//        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.SYS_CONFIG_KEY_CHARSETS);
        OutputStreamWriter outBatch = new OutputStreamWriter(fileOutputStream, SystemConstant.CHARSET_NAME);
        BufferedWriter bufferedWriter = new BufferedWriter(outBatch);
        try {
            while (!over) {
                List<ExamStudentAnswer> examStudentAnswers = examStudentAnswerService
                        .findRecordExistsAnswerByExamCode(examPlan.getExamCode(), skip, limit);
                if (examStudentAnswers.size() < limit) {
                    over = true;
                }
                for (ExamStudentAnswer answer : examStudentAnswers) {
                    if (answer == null || StringUtils.isEmpty(answer.getPaperName())) {
                        continue;
                    }
                    if (answer.getIsAbsent()) {
                        continue;
                    }
//					ExamStudent examStudent = answer.getStudent();
                    ExamStudent examStudent = examStudentService.getById(answer.getStudentId());
                    if (StringUtils.isEmpty(examStudent.getTicketNo())) {
                        throw new JkServerException("缺少准考证号,考生ID=" + examStudent.getId());
                    }
                    if (StringUtils.isEmpty(answer.getPaperName())) {
                        throw new JkServerException("缺少试卷ID,考生ID=" + examStudent.getId());
                    }
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(examStudent.getTicketNo()).append(",");
                    stringBuffer.append(answer.getPaperName());
                    stringBuffer.append("\r\n");
                    bufferedWriter.write(stringBuffer.toString());
                }
                bufferedWriter.flush();
                skip = skip + limit;
            }
        } finally {
            if (bufferedWriter != null) {
                bufferedWriter.close();
            }
            if (fileOutputStream != null) {
                IOUtils.closeQuietly(fileOutputStream);
            }
        }
        InputStream inputStream = new FileInputStream(file);
        try {
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            IOUtils.copy(inputStream, zipOutputStream);
        } finally {
            if (inputStream != null) {
                IOUtils.closeQuietly(inputStream);
            }
            zipOutputStream.closeEntry();
        }
    }

}
