package com.qmth.paper.library;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.paper.library.business.entity.PaperLibrary;
import com.qmth.paper.library.business.entity.PaperLibraryOther;
import com.qmth.paper.library.business.entity.PaperScanTask;
import com.qmth.paper.library.business.service.*;
import com.qmth.paper.library.common.contant.SystemConstant;
import com.qmth.paper.library.common.entity.*;
import com.qmth.paper.library.common.enums.*;
import com.qmth.paper.library.common.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 批量增加考生、图片数据
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class BatchInsertDataTest {

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

    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private BasicSemesterService basicSemesterService;
    @Resource
    private BasicExamService basicExamService;
    @Resource
    private ExamStudentService examStudentService;
    @Resource
    private PaperScanTaskService paperScanTaskService;
    @Resource
    private PaperLibraryService paperLibraryService;
    @Resource
    private PaperLibraryOtherService paperLibraryOtherService;
    @Resource
    private BasicFileTypeService basicFileTypeService;

    // 学校ID
    private static final Long schoolId = 140l;
    // 扫描员数量
    private static final int smUserCount = 8;
    // 学期数量
    private static final int semesterCount = 4;
    // 学期下考试数量
    private static final int examCount = 2;
    // 考试下考生数量
    private static final int examStudentCount = 300000;
    // 每个课程考生数量
    private static final int courseStudentCount = 2000;
    // 每个考生试卷数量
    private static final int examStudentPictureCount = 4;
    // 每个任务下其它图片数量
    private static final int paperScanOtherCount = 2000;
    // 默认图片地址
    private static final String picturePath = "[{\"md5\":\"f2283618584f18483856dd85cd11cab0\",\"path\":\"/home/ops/paper-library/image/测试学校5/学期1/考试1/模拟电路与数字系统(二)-002(002)/U202114082/U202114082-17-1.jpg\",\"type\":\"local\",\"uploadType\":\"IMAGE\"},{\"md5\":\"e552f0eadb82c121cba50e1bae0a5569\",\"path\":\"/home/ops/paper-library/image/测试学校5/学期1/考试1/模拟电路与数字系统(二)-002(002)/U202114082/U202114082-17-2.jpg\",\"type\":\"local\",\"uploadType\":\"IMAGE\"}]";

    @Test
    public void insertData() {
        // 新建扫描员
        List<SysUser> sysUserList = this.saveSmUser();
        // 新建学期
        List<BasicSemester> basicSemesterList = this.saveSemester(schoolId);
        // 新建考试
        List<BasicExam> basicExamList = this.saveExam(basicSemesterList);
        // 新建考生
        List<ExamStudent> examStudentList = this.saveExamStudent(basicExamList);
        // 新建任务
        List<PaperScanTask> paperScanTaskList = this.savePaperScanTask(examStudentList);
        // 新建图片
        this.savePaperLibrary(paperScanTaskList, examStudentList, sysUserList);
        // 新建其它图片
        this.savePaperLibraryOther(paperScanTaskList);
    }

    private List<SysUser> saveSmUser() {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysRole::getType, RoleTypeEnum.SCANNER);
        List<SysRole> sysRoles = sysRoleService.list(queryWrapper);
        if (CollectionUtils.isEmpty(sysRoles)) {
            throw ExceptionResultEnum.ERROR.exception("未找到内置的扫描员角色");
        }
        Long roleId = sysRoles.get(0).getId();


        QueryWrapper<SysOrg> sysOrgQueryWrapper = new QueryWrapper<>();
        sysOrgQueryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId).eq(SysOrg::getType, OrgTypeEnum.SCHOOL);
        List<SysOrg> sysOrgList = sysOrgService.list(sysOrgQueryWrapper);
        if (CollectionUtils.isEmpty(sysOrgList)) {
            throw ExceptionResultEnum.ERROR.exception("未找到顶级机构");
        }
        Long orgId = sysOrgList.get(0).getId();
        String namePrefix = "sm";
        List<SysUser> list = new ArrayList<>();
        for (int i = 1; i <= smUserCount; i++) {
            String name = namePrefix + i;
            QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.lambda().eq(SysUser::getSchoolId, schoolId).eq(SysUser::getLoginName, name);
            List<SysUser> sysUserList = sysUserService.list(userQueryWrapper);
            if (CollectionUtils.isNotEmpty(sysUserList)) {
                list.add(sysUserList.get(0));
            } else {
                SysUser sysUser = new SysUser();
                sysUser.setId(SystemConstant.getDbUuid());
                sysUser.setSchoolId(schoolId);
                sysUser.setLoginName(name);
                sysUser.setRealName(name);
                sysUser.setOrgId(orgId);
                sysUser.setPassword("MTIzNDU2");
                sysUser.setEnable(true);
                sysUser.setPwdCount(1);
                sysUserService.save(sysUser);

                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setId(SystemConstant.getDbUuid());
                sysUserRole.setUserId(sysUser.getId());
                sysUserRole.setRoleId(roleId);
                sysUserRole.setEnable(true);
                sysUserRoleService.save(sysUserRole);
                list.add(sysUser);
            }
        }
        return list;
    }

    private void savePaperLibraryOther(List<PaperScanTask> paperScanTaskList) {
        QueryWrapper<BasicFileType> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicFileType::getSchoolId, schoolId);
        List<BasicFileType> basicFileTypes = basicFileTypeService.list(queryWrapper);
        Long fileTypeId = 1L;
        if (CollectionUtils.isNotEmpty(basicFileTypes)) {
            fileTypeId = basicFileTypes.get(0).getId();
        }

        List<PaperLibraryOther> list = new ArrayList<>();
        AtomicInteger i = new AtomicInteger(1);
        for (PaperScanTask paperScanTask : paperScanTaskList) {
            for (int i1 = 0; i1 < paperScanOtherCount; i1++) {
                PaperLibraryOther paperLibraryOther = new PaperLibraryOther();
                paperLibraryOther.setId(SystemConstant.getDbUuid());
                paperLibraryOther.setPaperScanTaskId(paperScanTask.getId());
                paperLibraryOther.setPath(picturePath);
                paperLibraryOther.setSequence(i.getAndIncrement());
                paperLibraryOther.setFileTypeId(fileTypeId);
                list.add(paperLibraryOther);
            }
        }
        paperLibraryOtherService.saveBatch(list, 2000);

    }

    private void savePaperLibrary(List<PaperScanTask> paperScanTaskList, List<ExamStudent> examStudentList, List<SysUser> sysUserList) {
        Map<String, Long> paperScanTaskMap = paperScanTaskList.stream().collect(Collectors.toMap(m -> m.getExamId() + "#" + m.getCourseCode(), n -> n.getId()));
        Map<String, List<ExamStudent>> collect = examStudentList.stream().collect(Collectors.groupingBy(m -> m.getExamId() + "#" + m.getCourseCode()));
        List<PaperLibrary> list = new ArrayList<>();
        AtomicInteger batchNoInt = new AtomicInteger(1);
        for (Map.Entry<String, List<ExamStudent>> entry : collect.entrySet()) {
            Long createId = this.getRandomUserId(sysUserList);

            Date date = this.getRandomDateTime(300);

            AtomicInteger i = new AtomicInteger(1);
            Long paperScanTaskId = paperScanTaskMap.get(entry.getKey());
            String batchNo = "A" + batchNoInt.getAndIncrement();
            for (ExamStudent examStudent : entry.getValue()) {
                for (int i1 = 0; i1 < examStudentPictureCount; i1++) {
                    PaperLibrary paperLibrary = new PaperLibrary();
                    paperLibrary.setId(SystemConstant.getDbUuid());
                    paperLibrary.setSchoolId(schoolId);
                    paperLibrary.setPaperScanTaskId(paperScanTaskId);
                    paperLibrary.setPath(picturePath);
                    paperLibrary.setStudentId(examStudent.getId());
                    paperLibrary.setSequence(i.getAndIncrement());
                    paperLibrary.setBindResult(examStudent.getStudentCode());
                    paperLibrary.setBatchNo(batchNo);
                    paperLibrary.setCreateId(createId);
                    paperLibrary.setCreateTime(date.getTime());
                    paperLibrary.setCreateDate(DateFormatUtils.format(date, SystemConstant.SHORT_DATE_PATTERN));
                    list.add(paperLibrary);
                }
            }
        }
        paperLibraryService.saveBatch(list, 2000);
    }

    private Date getRandomDateTime(int i) {
        Random random = new Random();
        return DateUtils.addDays(new Date(), random.nextInt(i));
    }

    private Long getRandomUserId(List<SysUser> sysUserList) {
        Random random = new Random();
        int index = random.nextInt(sysUserList.size());
        return sysUserList.get(index).getId();
    }

    private List<PaperScanTask> savePaperScanTask(List<ExamStudent> examStudentList) {
        List<PaperScanTask> list = new ArrayList<>();
        Map<String, Long> examMap = examStudentList.stream().collect(Collectors.groupingBy(m -> m.getExamId() + "#" + m.getCourseCode() + "#" + m.getCourseName(), Collectors.counting()));
        for (Map.Entry<String, Long> entry : examMap.entrySet()) {
            String[] keys = entry.getKey().split("#");
            PaperScanTask paperScanTask = new PaperScanTask();
            paperScanTask.setId(SystemConstant.getDbUuid());
            paperScanTask.setSchoolId(schoolId);
            paperScanTask.setExamId(Long.valueOf(keys[0]));
            paperScanTask.setScanTaskCode(String.valueOf(System.nanoTime()));
            paperScanTask.setScanTaskName(String.format("%s（%s）", keys[2], keys[1]));
            paperScanTask.setCourseCode(keys[1]);
            paperScanTask.setCourseName(keys[2]);
            paperScanTask.setRecognitionType(RecognitionTypeEnum.BAR_CODE);
            paperScanTask.setStoreType(StoreTypeEnum.ROOM);
            paperScanTask.setStudentCount(entry.getValue().intValue());
            paperScanTask.setScanStudentCount(paperScanTask.getStudentCount());
            paperScanTask.setScanCount(paperScanTask.getScanStudentCount() * examStudentPictureCount);
            list.add(paperScanTask);
        }
        paperScanTaskService.saveBatch(list, 2000);
        return list;
    }

    private List<ExamStudent> saveExamStudent(List<BasicExam> basicExamList) {
        String courseCode = "kc";
        String courseName = "课程";
        int studentCodeInit = 100000000;
        String studentName = "考生";
        List<ExamStudent> list = new ArrayList<>();
        Random random = new Random();
        for (BasicExam basicExam : basicExamList) {
            int i = 1;
            for (int i1 = 1; i1 <= examStudentCount; i1++) {
                ExamStudent examStudent = new ExamStudent();
                examStudent.setId(SystemConstant.getDbUuid());
                examStudent.setSchoolId(schoolId);
                examStudent.setSemesterId(basicExam.getSemesterId());
                examStudent.setExamId(basicExam.getId());
                examStudent.setCourseCode(courseCode + i);
                examStudent.setCourseName(courseName + i);
                examStudent.setStudentCode(String.valueOf(studentCodeInit + i1));
                examStudent.setStudentName(studentName + i1);
                examStudent.setCollegeName("测试学院" + i);
                examStudent.setMajorName("测试专业" + i);
                examStudent.setClassName("测试班级" + i);
                examStudent.setTeacher("老师" + i);
                examStudent.setTeachClass("教学班" + i);
                examStudent.setExamRoom("考场" + i);
                examStudent.setScore(Double.valueOf(random.nextInt(100)));
                examStudent.setEnable(true);
                examStudent.setBindCount(examStudentPictureCount);
                list.add(examStudent);

                if (list.size() % courseStudentCount == 0) {
                    i++;
                }
            }
        }
        examStudentService.saveBatch(list, 2000);
        return list;
    }

    private List<BasicExam> saveExam(List<BasicSemester> basicSemesterList) {
        List<BasicExam> list = new ArrayList<>();
        String name = "测试考试";
        for (BasicSemester semester : basicSemesterList) {
            for (int i1 = 1; i1 <= examCount; i1++) {
                String examName = name + i1;
                QueryWrapper<BasicExam> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(BasicExam::getSchoolId, schoolId).eq(BasicExam::getSemesterId, semester.getId()).eq(BasicExam::getName, examName);
                List<BasicExam> exams = basicExamService.list(queryWrapper);
                if (CollectionUtils.isNotEmpty(exams)) {
                    list.add(exams.get(0));
                } else {
                    BasicExam basicExam = new BasicExam();
                    basicExam.setId(SystemConstant.getDbUuid());
                    basicExam.setSchoolId(schoolId);
                    basicExam.setSemesterId(semester.getId());
                    basicExam.setName(examName);
                    basicExamService.save(basicExam);
                    list.add(basicExam);
                }
            }
        }
        return list;
    }

    private List<BasicSemester> saveSemester(Long schoolId) {
        List<BasicSemester> list = new ArrayList<>();
        String name = "测试学期";
        for (int i = 1; i <= semesterCount; i++) {
            String semesterName = name + i;
            QueryWrapper<BasicSemester> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BasicSemester::getSchoolId, schoolId).eq(BasicSemester::getName, semesterName);
            List<BasicSemester> semesters = basicSemesterService.list(queryWrapper);
            if (CollectionUtils.isNotEmpty(semesters)) {
                list.add(semesters.get(0));
            } else {
                BasicSemester basicSemester = new BasicSemester();
                basicSemester.setId(SystemConstant.getDbUuid());
                basicSemester.setSchoolId(schoolId);
                basicSemester.setName(semesterName);
                basicSemester.setEnable(true);
                basicSemesterService.save(basicSemester);
                list.add(basicSemester);
            }
        }
        return list;
    }
}
