package com.qmth.themis.business.forkjoin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
import com.qmth.themis.business.constant.SpringContextHolder;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.ExamStudentImportDto;
import com.qmth.themis.business.entity.TEExamActivity;
import com.qmth.themis.business.entity.TEExamStudent;
import com.qmth.themis.business.entity.TEStudent;
import com.qmth.themis.business.enums.ExamModeEnum;
import com.qmth.themis.business.service.TEExamCourseService;
import com.qmth.themis.business.service.TEExamStudentService;
import com.qmth.themis.business.service.TEStudentService;
import com.qmth.themis.common.util.Base64Util;
import com.qmth.themis.common.util.GsonUtil;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.concurrent.RecursiveTask;

/**
 * @Description: 考生导入forkjoin
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2022/10/31
 */
public class ExamStudentImportForkJoin extends RecursiveTask<Set<String>> {

    private List<ExamStudentImportDto> list;

    // 每个"小任务"最多执行保存500个数
    private static int MAX = 500;

    private int start;

    private int end;

    private ExamModeEnum modeEnum;

    private Map<String, TEExamActivity> teExamActivityMap;

    private Long examId;

    private Long orgId;

    private Long createId;

    private Set<String> roomCodeAndNameSet = new HashSet<>();

    public ExamStudentImportForkJoin(int start, int end, List<ExamStudentImportDto> list,
                                     ExamModeEnum modeEnum,
                                     Map<String, TEExamActivity> teExamActivityMap,
                                     Long examId,
                                     Long orgId,
                                     Long createId) {
        this.start = start;
        this.end = end;
        this.list = list;
        this.modeEnum = modeEnum;
        this.teExamActivityMap = teExamActivityMap;
        this.examId = examId;
        this.orgId = orgId;
        this.createId = createId;
    }

    @Override
    protected Set<String> compute() {
        if ((end - start) <= MAX) {
            TEExamActivity teExamActivity = null;
            if (Objects.equals(modeEnum, ExamModeEnum.ANYTIME)) {
                Iterator iterator = teExamActivityMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Map> entry = (Map.Entry<String, Map>) iterator.next();
                    Map m = entry.getValue();
                    teExamActivity = GsonUtil.fromJson(GsonUtil.toJson(m), TEExamActivity.class);
                }
            }
            TEExamStudentService teExamStudentService = SpringContextHolder.getBean(TEExamStudentService.class);
            TEStudentService teStudentService = SpringContextHolder.getBean(TEStudentService.class);
            TEExamCourseService teExamCourseService = SpringContextHolder.getBean(TEExamCourseService.class);

            List<TEExamStudent> teExamStudentInsertList = new ArrayList<>();
            List<TEExamStudent> teExamStudentUpdateList = new ArrayList<>();
            Map<String, TEStudent> teStudentInsertMap = new HashMap<>();
            Map<String, TEStudent> teStudentUpdateMap = new HashMap<>();
            for (int i = start; i <= end; i++) {
                ExamStudentImportDto examStudentImportDto = (ExamStudentImportDto) list.get(i);
                if (Objects.equals(modeEnum, ExamModeEnum.TOGETHER)) {
                    Map m = (Map) teExamActivityMap.get(examStudentImportDto.getExamActivityCode());
                    teExamActivity = GsonUtil.fromJson(GsonUtil.toJson(m), TEExamActivity.class);
                }
                //先根据证件号+科目代码查询考生是否存在，存在则更新，不存在则插入
                QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
                teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getIdentity, examStudentImportDto.getIdentity())
                        .eq(TEExamStudent::getCourseCode, examStudentImportDto.getCourseCode())
                        .eq(TEExamStudent::getExamId, examId)
                        .eq(TEExamStudent::getExamActivityId, teExamActivity.getId());
                TEExamStudent teExamStudent = teExamStudentService.getOne(teExamStudentQueryWrapper);
                //如果为空则插入考生数据，插入考生前先插入学生档案数据
                QueryWrapper<TEStudent> teStudentQueryWrapper = new QueryWrapper<>();
                teStudentQueryWrapper.lambda().eq(TEStudent::getIdentity, examStudentImportDto.getIdentity()).eq(TEStudent::getOrgId, orgId);
                TEStudent teStudent = teStudentService.getOne(teStudentQueryWrapper);
                boolean teStudentExists = false, teExamStudentExists = false;
                if (Objects.isNull(teExamStudent)) {
                    teExamStudentExists = true;
                    if (Objects.isNull(teStudent)) {//如果学生数据为空则插入学生数据
                        //先插入学生档案数据
                        teStudentExists = true;
                        teStudent = new TEStudent(orgId, examStudentImportDto.getIdentity(), examStudentImportDto.getName(), createId);
                    }
                    teExamStudent = GsonUtil.fromJson(GsonUtil.toJson(examStudentImportDto), TEExamStudent.class);
                    teExamStudent.setIdentity(examStudentImportDto.getIdentity());
                    teExamStudent.setExamId(examId);
                    teExamStudent.setStudentId(teStudent.getId());
                    teExamStudent.setCreateId(createId);
                } else {
                    teExamStudent.setUpdateId(createId);
                    teExamStudent.setName(examStudentImportDto.getName());
                    teExamStudent.setGrade(examStudentImportDto.getGrade());
                    teExamStudent.setClassNo(examStudentImportDto.getClassNo());
                    teExamStudent.setRoomCode(examStudentImportDto.getRoomCode());
                    teExamStudent.setRoomName(examStudentImportDto.getRoomName());
                }
                teExamStudent.setCourseCode(examStudentImportDto.getCourseCode());
                teExamStudent.setCourseName(examStudentImportDto.getCourseName());
                teExamStudent.setExamActivityId(teExamActivity.getId());
                if (Objects.nonNull(examStudentImportDto.getPassword()) && !Objects.equals(examStudentImportDto.getPassword(), "")) {
                    try {
                        teStudent.setPassword(Base64Util.encode(examStudentImportDto.getPassword().getBytes(SystemConstant.CHARSET_NAME)));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                } else {
                    if (Objects.isNull(teStudent.getPassword())) {
                        teStudent.setPassword(SystemConstant.DEFAULT_PASSWORD);
                    }
                }
                teStudent.setMobileNumber(examStudentImportDto.getMobileNumber());
                teStudent.setName(examStudentImportDto.getName());
                if (teStudentExists) {
                    if (!teStudentInsertMap.containsKey(teStudent.toString())) {
                        teStudentInsertMap.put(teStudent.toString(), teStudent);
                        teExamStudent.setStudentId(teStudent.getId());
                    } else {
                        TEStudent student = teStudentInsertMap.get(teStudent.toString());
                        teExamStudent.setStudentId(student.getId());
                    }
                } else {
                    if (!teStudentUpdateMap.containsKey(teStudent.toString())) {
                        teStudentUpdateMap.put(teStudent.toString(), teStudent);
                    } else {
                        TEStudent student = teStudentUpdateMap.get(teStudent.toString());
                        teExamStudent.setStudentId(student.getId());
                    }
                }

                ExamCourseCacheBean examCourseCacheBean = teExamCourseService.getExamCourseCacheBean(teExamStudent.getExamId(), teExamStudent.getCourseCode());
                if (Objects.nonNull(examCourseCacheBean)) {
                    teExamStudent.setCourseName(examCourseCacheBean.getCourseName());
                }
                teExamStudent.setAlreadyExamCount(Objects.isNull(teExamStudent.getAlreadyExamCount()) ? 0 : teExamStudent.getAlreadyExamCount());
                roomCodeAndNameSet.add(examId + ":" + teExamStudent.getRoomCode() + ":" + teExamStudent.getRoomName());
                if (teExamStudentExists) {
                    teExamStudentInsertList.add(teExamStudent);
                } else {
                    teExamStudentUpdateList.add(teExamStudent);
                }
            }
            if (!CollectionUtils.isEmpty(teStudentInsertMap)) {
                teStudentService.saveBatch(teStudentInsertMap.values());
            }
            if (!CollectionUtils.isEmpty(teStudentUpdateMap)) {
                teStudentService.updateBatchById(teStudentUpdateMap.values());
            }
            if (!CollectionUtils.isEmpty(teExamStudentInsertList)) {
                teExamStudentService.saveBatch(teExamStudentInsertList);
            }
            if (!CollectionUtils.isEmpty(teExamStudentUpdateList)) {
                teExamStudentService.updateBatchById(teExamStudentUpdateList);
            }
            return roomCodeAndNameSet;
        } else {
            // 将大任务分解成两个小任务
            int middle = (start + end) / 2;
            ExamStudentImportForkJoin left = new ExamStudentImportForkJoin(start, middle, list, modeEnum, teExamActivityMap, examId, orgId, createId);
            ExamStudentImportForkJoin right = new ExamStudentImportForkJoin(middle + 1, end, list, modeEnum, teExamActivityMap, examId, orgId, createId);
            invokeAll(left, right);

            roomCodeAndNameSet.addAll(left.join());
            roomCodeAndNameSet.addAll(right.join());
        }
        return roomCodeAndNameSet;
    }
}
