package cn.com.qmth.stmms.admin.thread;

import cn.com.qmth.stmms.admin.utils.HttpUtil;
import cn.com.qmth.stmms.biz.exam.model.DataSync;
import cn.com.qmth.stmms.biz.exam.model.Exam;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.service.DataSyncService;
import cn.com.qmth.stmms.biz.exam.service.ExamService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.file.enums.FormatType;
import cn.com.qmth.stmms.biz.file.service.FileService;
import cn.com.qmth.stmms.biz.lock.LockService;
import cn.com.qmth.stmms.common.enums.LockType;
import cn.com.qmth.stmms.common.enums.SubjectiveStatus;

import com.aliyun.oss.common.utils.BinaryUtil;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DataSyncThread implements Runnable {

    protected static Logger log = LoggerFactory.getLogger(DataSyncThread.class);

    private DataSync dataSync;

    private ExamStudentService studentService;

    private ExamSubjectService subjectService;

    private ExamService examService;

    private FileService fileService;

    private LockService lockService;

    private DataSyncService dataSyncService;

    private Integer pageSize;

    private HttpUtil subjectHttp;

    private HttpUtil studentHttp;

    private HttpUtil subjectPaperHttp;

    public static final String PAPER_STRUCT = "paperStructList";

    public static final String SUBJECT_CODE = "subjectCode";

    public static final String SUBJECT_NAME = "subjectName";

    public static final String SUBJECTIVES = "subjectives";

    public static final String DATA_LIST = "dataList";

    public static final String START_ID = "startId";

    public static final String NEXT_ID = "nextId";

    public static final String DEFAULT_NULL = "#";

    public static final String SIZE = "size";

    public static final String ERROR_CODE = "EX-101444";

    public DataSyncThread(DataSync dataSync, Integer pageSize, LockService lockService,
            DataSyncService dataSyncService, ExamService examService, ExamStudentService studentService,
            ExamSubjectService subjectService, FileService fileService) {
        this.dataSync = dataSync;
        this.lockService = lockService;
        this.dataSyncService = dataSyncService;
        this.examService = examService;
        this.studentService = studentService;
        this.subjectService = subjectService;
        this.fileService = fileService;
        this.pageSize = pageSize;
        this.subjectHttp = new HttpUtil(dataSync.getSubjectUrl(), dataSync.getAccessKey(), dataSync.getAppId(),
                dataSync.getRootOrgId());
        this.studentHttp = new HttpUtil(dataSync.getStudentUrl(), dataSync.getAccessKey(), dataSync.getAppId(),
                dataSync.getRootOrgId());
        this.subjectPaperHttp = new HttpUtil(dataSync.getSubjectPaperUrl(), dataSync.getAccessKey(),
                dataSync.getAppId(), dataSync.getRootOrgId());
    }

    @Override
    public void run() {
        log.info("start data sync for examId=" + dataSync.getExamId());
        try {
            JSONObject datas = new JSONObject();
            datas.accumulate("examId", Long.parseLong(dataSync.getCloudExamId()));
            String subjectResult = subjectHttp.httpAction(null, datas.toString());
            JSONObject subjectJson = JSONObject.fromObject(subjectResult);
            // 考试返回错误，无法创建阅卷
            if (!subjectJson.getString("code").isEmpty()) {
                log.error("data sync exception for cloud examId=" + dataSync.getCloudExamId(),
                        subjectJson.getString("desc"));
                return;
            }
            // 获取考试信息
            Exam exam = examService.findById(dataSync.getExamId());
            dataSync.setSchoolId(exam.getSchoolId());
            DataSync sync = dataSyncService.findByExamId(dataSync.getExamId());
            if (sync == null) {
                sync = dataSync;
                sync.setCreateTime(new Date());
                dataSyncService.save(sync);
            }

            JSONArray subjectArray = subjectJson.getJSONArray(PAPER_STRUCT);
            for (int i = 0; i < subjectArray.size(); i++) {
                JSONObject subject = subjectArray.getJSONObject(i);
                String subjectCode = subject.getString(SUBJECT_CODE);
                String subjectName = subject.getString(SUBJECT_NAME);
                // 获取试卷内容
                datas.put(SUBJECT_CODE, subjectCode);
                String paperResult = subjectPaperHttp.httpAction(null, datas.toString());
                JSONObject paperJson = JSONObject.fromObject(paperResult);
                String paper = paperJson.getString("subjectivePaper");
                byte[] paperData = paper.getBytes(StandardCharsets.UTF_8);
                fileService.uploadPaper(new ByteArrayInputStream(paperData), BinaryUtil.encodeMD5(paperData),
                        exam.getId(), subjectCode, FormatType.JSON);

                ExamSubject examSubject = subjectService.find(exam.getId(), subjectCode);
                if (examSubject != null && !subjectCode.equals(sync.getSubjectCode())) {
                    continue;
                }
                // 创建科目
                this.saveSubject(exam.getId(), subjectCode, subjectName);
                // 获取考生
                Long startId = 0L;
                if (null != sync.getNextId()) {
                    startId = sync.getNextId();
                }
                while (startId != null) {
                    datas.put(SUBJECT_CODE, subjectCode);
                    datas.put(START_ID, startId);
                    datas.put(SIZE, pageSize);
                    String studentResult = studentHttp.httpAction(null, datas.toString());

                    JSONObject studentJson = JSONObject.fromObject(studentResult);

                    Long nextId = studentJson.getLong(NEXT_ID);
                    if (startId - nextId == 0) {
                        startId = null;
                    } else {
                        startId = nextId;
                    }
                    Object obj = studentJson.get(DATA_LIST);
                    if (obj instanceof JSONObject && ((JSONObject) obj).isNullObject()) {
                        sync.setUpdateTime(new Date());
                        sync.setNextId(startId);
                        dataSyncService.save(sync);
                        continue;
                    }
                    JSONArray studentArray = studentJson.getJSONArray(DATA_LIST);
                    List<ExamStudent> list = new ArrayList<ExamStudent>();
                    Date now = new Date();
                    for (int j = 0; j < studentArray.size(); j++) {
                        JSONObject student = studentArray.getJSONObject(j);
                        ExamStudent examStudent = new ExamStudent();
                        examStudent.setExamId(sync.getExamId());

                        examStudent.setStudentCode(student.getString("studentCode"));
                        examStudent.setName(student.getString("name"));
                        examStudent.setCollege(DEFAULT_NULL);
                        examStudent.setClassName(DEFAULT_NULL);
                        examStudent.setTeacher(DEFAULT_NULL);
                        examStudent.setCampusName(DEFAULT_NULL);
                        examStudent.setSubjectCode(subjectCode);
                        examStudent.setSubjectName(subjectName);
                        examStudent.setExamNumber(student.getString("examNumber"));
                        examStudent.setPaperType(DEFAULT_NULL);

                        examStudent.setSchoolId(exam.getSchoolId());
                        examStudent.setAbsent(false);
                        examStudent.setUpload(true);
                        examStudent.setManualAbsent(false);
                        examStudent.setBreach(false);
                        examStudent.setException(false);
                        examStudent.setSliceCount(0);
                        examStudent.setSheetCount(0);
                        examStudent.setObjectiveScore(0d);
                        examStudent.setSubjectiveScore(0d);
                        examStudent.setSubjectiveStatus(SubjectiveStatus.UNMARK);
                        examStudent.setAnswers(null);
                        examStudent.setBatchCode(null);
                        examStudent.setUploadTime(now);
                        examStudent.setInspectCount(0);
                        examStudent.setSecretNumber(student.getString("examNumber"));
                        list.add(examStudent);

                        String answerJson = student.getString(SUBJECTIVES);
                        byte[] jsonData = answerJson.getBytes(StandardCharsets.UTF_8);
                        fileService.uploadJson(new ByteArrayInputStream(jsonData), BinaryUtil.encodeMD5(jsonData),
                                exam.getId(), examStudent.getSecretNumber());
                    }
                    int count = studentService.batchSave(list);
                    if (count > 0) {
                        subjectService.updateUploadCount(exam.getId(), subjectCode,
                                (int) studentService.countUploadedByExamIdAndSubjectCode(exam.getId(), subjectCode));
                    }
                    sync.setUpdateTime(new Date());
                    sync.setNextId(startId);
                    sync.setSubjectCode(subjectCode);
                    dataSyncService.save(sync);
                }
            }
            sync.setFinished(true);
            dataSyncService.save(sync);
        } catch (Exception e) {
            log.error("data sync exception for examId=" + dataSync.getExamId(), e);
        } finally {
            lockService.unlock(LockType.DATA_SYNC, dataSync.getExamId());
            log.info("finish data sync for examId=" + dataSync.getExamId());
        }
    }

    private void saveSubject(Integer examId, String subjectCode, String subjectName) {
        ExamSubject subject = new ExamSubject();
        subject.setExamId(examId);
        subject.setCode(subjectCode);
        subject.setName(subjectName);
        subject.setPaperFileType(FormatType.JSON);
        subject.setAnswerFileType(FormatType.JSON);
        subject.setObjectiveScore(0d);
        subject.setSubjectiveScore(0d);
        subject.setTotalScore(0d);
        subject.setUploadCount(0);
        subject.setDisplayQuestionName(false);
        subject.setInspectRound(1);
        subject.setSelective(false);
        subjectService.save(subject);
    }

}
