package com.xjrsoft.module.job;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.gson.JsonArray;
import com.xjrsoft.XjrSoftApplication;
import com.xjrsoft.common.enums.CourseAdjustTypeEnum;
import com.xjrsoft.common.enums.EnabledMark;
import com.xjrsoft.common.enums.WorkflowApproveType;
import com.xjrsoft.common.enums.WorkflowMultiInstanceType;
import com.xjrsoft.common.mybatis.SqlRunnerAdapter;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.config.CommonPropertiesConfig;
import com.xjrsoft.module.base.entity.BaseClass;
import com.xjrsoft.module.base.service.IBaseClassService;
import com.xjrsoft.module.courseTable.entity.CourseTable;
import com.xjrsoft.module.courseTable.service.ICourseTableService;
import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.organization.service.IUserService;
import com.xjrsoft.module.organization.service.IWeChatService;
import com.xjrsoft.module.schedule.entity.CourseTableBak;
import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
import com.xjrsoft.module.schedule.service.ICourseTableBakService;
import com.xjrsoft.module.schedule.service.IWfCourseAdjustService;
import com.xjrsoft.module.schedule.util.DataUtil;
import com.xjrsoft.module.teacher.entity.BaseTeacher;
import com.xjrsoft.module.workflow.constant.WorkflowConstant;
import com.xjrsoft.module.workflow.entity.WorkflowExtra;
import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
import com.xjrsoft.module.workflow.entity.WorkflowRecord;
import com.xjrsoft.module.workflow.entity.XjrWorkflowOperateRecord;
import com.xjrsoft.module.workflow.mapper.XjrWorkflowOperateRecordMapper;
import com.xjrsoft.module.workflow.service.IWorkflowExecuteService;
import com.xjrsoft.module.workflow.service.IWorkflowExtraService;
import com.xjrsoft.module.workflow.service.IWorkflowFormRelationService;
import com.xjrsoft.module.workflow.service.IWorkflowRecordService;
import me.zhyd.oauth.log.Log;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author dzx
 * @date 2024/10/15
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = XjrSoftApplication.class)
class JianyuekbScheduleTaskTest2 {
    @Autowired
    private IBaseClassService classService;

    private final static String taskKey = "jianyuekbScheduleTask";

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IWfCourseAdjustService adjustService;

    @Autowired
    private ICourseTableService courseTableService;

    @Autowired
    private ICourseTableBakService courseTableBakService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private IWorkflowFormRelationService formRelationService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private IWorkflowExecuteService workflowExecuteService;

    @Autowired
    private IWorkflowRecordService workflowRecordService;

    @Autowired
    private XjrWorkflowOperateRecordMapper xjrWorkflowOperateRecordMapper;

    private final static String wechatTemplate = "OO5Ryu9_6Hh5LQW0aKG7qu3g5uV8VxvBusq1i5UFesk";

    @Autowired
    private IWeChatService weChatService;

    @Autowired
    private CommonPropertiesConfig commonPropertiesConfig;

    @Autowired
    private IUserService userService;

    @Autowired
    private IWorkflowExtraService workflowExtraService;

    @Test
    public void execute(){
        doExecute();
    }
    public void doExecute() {
        String sql = "SELECT * FROM course_receive_msg WHERE delete_mark = 0 AND is_callback = -1";
        List<Map<String, Object>> receiveMsgs = SqlRunnerAdapter.db().selectList(sql);
        if(receiveMsgs.isEmpty()){
            return;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //查询出传入排课系统的年级和班级
        List<String> eduYearSerialNo1 = receiveMsgs.stream().map(x -> "'" + x.get("edu_year_serial_no").toString() + "'").collect(Collectors.toList());

        //查询出传入排课系统的年级和班级
        sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''" +
                " and table_name = 'base_grade'" +
                " and jianyue_id in (" + eduYearSerialNo1.toString().replace("[","").replace("]","") + ")";
        List<Map<String, Object>> jianyueData = SqlRunnerAdapter.db().selectList(sql);
        Map<String, List<BaseClass>> gradeClassMaps = new HashMap<>();//存入对应年级的所有班级id
        for (Map<String, Object> el : jianyueData) {
            String gradeId = el.get("source_id").toString();
            String orgId = null;
            if(gradeId.contains("_")){
                String[] split = el.get("source_id").toString().split("_");
                gradeId = split[1];
                orgId = split[0];
            }
            List<BaseClass> classList = classService.list(
                    new QueryWrapper<BaseClass>().lambda()
                            .eq(BaseClass::getGradeId, gradeId)
                            .eq(BaseClass::getOrgId, orgId)
            );
            gradeClassMaps.put(el.get("jianyue_id").toString(), classList);
        }
        LocalDate today = LocalDate.now();

        DataUtil dataUtil = new DataUtil();
        Set<String> ongoing = redisUtil.get(taskKey, new TypeReference<Set<String>>() {});//正在进行中的
        if(ongoing == null){
            ongoing = new HashSet<>();
        }

        Map<String, Map<String, String>> dataMap = initDataMap();
        for (Map<String, Object> receiveMsg : receiveMsgs) {
            String eduYearSerialNo = receiveMsg.get("edu_year_serial_no").toString();
            if(ongoing.contains(eduYearSerialNo)){
                continue;
            }
            ongoing.add(eduYearSerialNo);
            redisUtil.set(taskKey, ongoing);

            try {
                String updSql = "update course_receive_msg set is_callback = 0 where id = " + receiveMsg.get("id").toString();
                SqlRunnerAdapter.db().update(updSql);

                JsonArray allScheduleInfo = new JsonArray();
                String startDateStr = receiveMsg.get("start_date").toString();
                LocalDate startDateObj = LocalDate.parse(startDateStr);
                String endDateStr = receiveMsg.get("end_date").toString();
                LocalDate endDateObj = LocalDate.parse(endDateStr);
                if(today.isAfter(startDateObj)){
                    startDateStr = today.format(formatter);
                }

                //删除课表信息;
                List<BaseClass> classList = gradeClassMaps.get(eduYearSerialNo);
                List<Long> classIdList = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
                String classIds = classIdList.toString().replace("[", "").replace("]", "");
                String delSql = "delete from course_table where schedule_date between '" + startDateStr + "'" +
                        " and '" + endDateStr +
                        "' and class_id in (" + classIds + ")";
                SqlRunnerAdapter.db().delete(delSql);


                startDateStr = receiveMsg.get("start_date").toString();
                List<String> processIds = suspendedCourseAdjust(classList, startDateStr, endDateStr);

                long between = ChronoUnit.DAYS.between(startDateObj, endDateObj);
                int times = Integer.parseInt(((between / 7) + 1) + "");

                for (int index = 0; index < times; index ++) {
                    LocalDate statrTime = startDateObj.plusDays(index * 7L);
                    String startDate = statrTime.format(formatter);
                    LocalDate endTime = statrTime.plusDays(6L);
                    if(endTime.isAfter(endDateObj)){
                        endTime = endDateObj;
                    }

                    String endDate = endTime.format(formatter);
                    //获取课表并存到数据库
                    JsonArray scheduleInfo = dataUtil.getScheduleInfoByGrade(eduYearSerialNo, startDate, endDate);
                    allScheduleInfo.addAll(scheduleInfo);
                }

                updSql = "update course_receive_msg set is_callback = 1 where id = " + receiveMsg.get("id").toString();
                SqlRunnerAdapter.db().update(updSql);

                ongoing.remove(eduYearSerialNo);
                redisUtil.set(taskKey, ongoing);
                insertCourse(allScheduleInfo, dataMap, dataUtil);
                //恢复挂起的流程
                restoreCourseAdjust(processIds);
                //处理该日期内已经审批通过的调课和顶课申请
                handleCourseAdjust(classList, startDateStr, endDateStr);
            }catch (Exception e){
                Log.error(e.getMessage(), e);
                ongoing.remove(eduYearSerialNo);
                redisUtil.set(taskKey, ongoing);
            }
        }
    }

    void insertCourse(JsonArray scheduleInfo, Map<String, Map<String, String>> dataMap, DataUtil dataUtil){
        //获取年级
        String tableName = "base_grade";
//            Map<String, Long> gradeMap = dataMap.get(tableName);
        //获取学期
        tableName = "base_semester";
        Map<String, String> semesterMap = dataMap.get(tableName);
        //获取课程
        tableName = "base_course_subject";
        Map<String, String> courseMap = dataMap.get(tableName);
        //获取教职工
        tableName = "base_teacher";
        Map<String, String> teacherMap = dataMap.get(tableName);
        //获取行政班
        tableName = "base_class";
        Map<String, String> classMap = dataMap.get(tableName);

        tableName = "base_classroom";
        Map<String, String> classroomMap = dataMap.get(tableName);

        dataUtil.insertCourseTableEntiy(scheduleInfo, classroomMap, courseMap, semesterMap, teacherMap, classMap);
        dataUtil.insertClassTime(scheduleInfo);
    }

    Map<String, Map<String, String>> initDataMap(){
        Map<String, Map<String, String>> dataMap = new HashMap<>();
        String sql = "SELECT distinct table_name FROM jianyue_data WHERE 1 = 1";
        List<Map<String, Object>> query = SqlRunnerAdapter.db().selectList(sql);
        Set<String> tables = new HashSet<>();
        for (Map<String, Object> jianyueData : query) {
            tables.add(jianyueData.get("table_name").toString());
        }
        sql = "SELECT * FROM jianyue_data WHERE source_id IS NOT NULL AND jianyue_id != ''";
        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);

        for (String table : tables) {
            Map<String, String> tableData = new HashMap<>();
            for (Map<String, Object> jianyueData : list) {
                if(!table.equals(jianyueData.get("table_name").toString())){
                    continue;
                }
                tableData.put(jianyueData.get("jianyue_id").toString(), jianyueData.get("source_id").toString());
            }
            dataMap.put(table, tableData);
        }
        return dataMap;
    }


    /**
     * 课程数据同步完之后，处理调课和顶课申请
     * 1、课程数据入库后，将新课表日期之后的的调课顶课数据再次更新到课表中
     * 2、筛选出课表变化了的调课和顶课申请，通知发起人
     */
    public void handleCourseAdjust(List<BaseClass> classList, String startDate, String endDate){
        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
        Map<Long, String> classMap = classList.stream().collect(Collectors.toMap(BaseClass::getId, BaseClass::getName));
        List<CourseTableBak> bakList = courseTableBakService.list(
                new QueryWrapper<CourseTableBak>().lambda()
                        .in(CourseTableBak::getClassId, classIds)
                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
        );
        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());
        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
        List<WfCourseAdjust> list = adjustService.list(
                new MPJLambdaWrapper<WfCourseAdjust>()
                        .select(WfCourseAdjust::getId)
                        .select(WfCourseAdjust.class, x -> VoToColumnUtil.fieldsToColumns(WfCourseAdjust.class).contains(x.getProperty()))
                        .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, WfCourseAdjust::getId)
                        .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED)
        );
        List<WfCourseAdjust> cancelList = new ArrayList<>();//需要作废的申请

        List<Long> userIds = list.stream().map(WfCourseAdjust::getUserId).collect(Collectors.toList());
        List<User> userList = userService.list(
                new MPJLambdaWrapper<User>()
                        .select(User::getId)
                        .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
                        .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
                        .in(!userIds.isEmpty(), User::getId, userIds)
        );
        Map<Long, String> userOpenIdMap = new HashMap<>();
        for (User user : userList) {
            userOpenIdMap.put(user.getId(), user.getOpenId());
        }

        for (WfCourseAdjust courseAdjust : list) {
            if(courseAdjust.getUserId() == 14954805813957L){
                System.out.println(courseAdjust.getId());
            }
            List<CourseTable> courseList = courseTableService.list(
                    new MPJLambdaWrapper<CourseTable>()
                            .select(CourseTable::getId)
                            .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty()))
                            .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo)
                            .eq(CourseTableBak::getWfCourseAdjustId, courseAdjust.getId())
            );

            String[] courseIds = courseAdjust.getCourseId().split(",");
            String[] exchangeCourseIds = null;
            int courseCount = courseIds.length;
            if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
                exchangeCourseIds = courseAdjust.getExchangeCourseId().split(",");
                courseCount += exchangeCourseIds.length;
            }
            if(courseList.size() != courseCount){
                //表明课程变化了，需要重新申请，需要将原来的申请作废并进行微信消息通知
                courseAdjust.setEnabledMark(EnabledMark.DISABLED.getCode());

                courseAdjust.setCancelReason("由于课表更新，当前调/顶课课程发生变化，该调顶课已失效，请重新发起调顶课");
                cancelList.add(courseAdjust);
                List<String> thing16Str = new ArrayList<>();
                List<String> thing2Str = new ArrayList<>();
                for (CourseTableBak tableBak : bakList) {
                    if(!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())){
                        continue;
                    }

                    thing16Str.add(classMap.get(tableBak.getId()));
                    thing2Str.add(tableBak.getClassName());
                }

                WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
                weChatSendMessageDto.setTemplateId(wechatTemplate);
                JSONObject paramJson = new JSONObject();

                JSONObject thing16 = new JSONObject();
                thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
                paramJson.put("thing16", thing16);

                JSONObject thing2 = new JSONObject();
                thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
                paramJson.put("thing2", thing2);

                String const12Str = "";
                if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
                    const12Str = "调课失败";
                } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
                    const12Str = "顶课失败";
                }

                JSONObject const12 = new JSONObject();
                const12.put("value", const12Str);
                paramJson.put("const23", const12);

                //迟到人数或者缺勤人数
                JSONObject thing5 = new JSONObject();
                thing5.put("value", "由于课表更新，该调顶课已失效");
                paramJson.put("thing5", thing5);

                String url = StrUtil.format(
                        "{}/xjrsoft/pages/workflow/look?processId={}&type=my",
                        commonPropertiesConfig.getDomainApp(),
                        "relation.getProcessId()"
                );
                weChatSendMessageDto.setContent(paramJson);
                weChatSendMessageDto.setUrl(url);
                weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
                String openId = userOpenIdMap.get(courseAdjust.getUserId());
                if(openId != null && !"".equals(openId)){
                    weChatSendMessageDto.setUserId(openId);
                    weChatService.sendTemplateMessage(weChatSendMessageDto);
                }
                continue;
            }
            courseTableService.adjustCourse(courseAdjust);
        }
        if(!cancelList.isEmpty()){
            adjustService.updateBatchById(cancelList);
        }

        List<WorkflowFormRelation> activeList = formRelationService.list(
                new MPJLambdaWrapper<WorkflowFormRelation>()
                        .select(WorkflowFormRelation::getId)
                        .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty()))
                        .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue)
                        .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
        );
        for (WorkflowFormRelation relation : activeList) {
            List<CourseTable> courseList = courseTableService.list(
                    new MPJLambdaWrapper<CourseTable>()
                            .select(CourseTable::getId)
                            .select(CourseTable.class, x -> VoToColumnUtil.fieldsToColumns(CourseTable.class).contains(x.getProperty()))
                            .innerJoin(CourseTableBak.class, CourseTableBak::getKeyInfo, CourseTable::getKeyInfo)
                            .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
            );
            List<CourseTableBak> thisbakList = courseTableBakService.list(
                    new QueryWrapper<CourseTableBak>().lambda()
                            .eq(CourseTableBak::getWfCourseAdjustId, relation.getFormKeyValue())
            );
            if(courseList.size() == thisbakList.size()){
                continue;
            }
            WfCourseAdjust courseAdjust = adjustService.getById(relation.getFormKeyValue());
            //表明课程变化了，进行内部终止
            List<String> thing16Str = new ArrayList<>();
            List<String> thing2Str = new ArrayList<>();
            for (CourseTableBak tableBak : bakList) {
                if(!tableBak.getWfCourseAdjustId().equals(courseAdjust.getId())){
                    continue;
                }

                thing16Str.add(classMap.get(tableBak.getId()));
                thing2Str.add(tableBak.getClassName());
            }

            WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
            weChatSendMessageDto.setTemplateId(wechatTemplate);
            JSONObject paramJson = new JSONObject();

            JSONObject thing16 = new JSONObject();
            thing16.put("value", thing16Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
            paramJson.put("thing16", classMap);

            JSONObject thing2 = new JSONObject();
            thing2.put("value", thing2Str.toString().replace(" ", "").replace("[", "").replace("]", ""));
            paramJson.put("thing2", thing2);

            String const12Str = "";
            if (CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())) {
                const12Str = "调课失败";
            } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
                const12Str = "顶课失败";
            }

            JSONObject const12 = new JSONObject();
            const12.put("value", const12Str);
            paramJson.put("const23", const12);

            //迟到人数或者缺勤人数
            JSONObject thing5 = new JSONObject();
            thing5.put("value", "由于课表更新，该调顶课已失效");
            paramJson.put("thing5", thing5);

            weChatSendMessageDto.setContent(paramJson);
            List<WorkflowExtra> extraList = workflowExtraService.list(
                    new QueryWrapper<WorkflowExtra>().lambda()
                            .eq(WorkflowExtra::getProcessId, relation.getProcessId())
                            .orderByDesc(WorkflowExtra::getStartTime)
            );

            if(!extraList.isEmpty()){
                String url = StrUtil.format(
                        "{}/xjrsoft/pages/workflow/approval?taskId={}&processId={}&type=todo",
                        commonPropertiesConfig.getDomainApp(),
                        extraList.get(0).getTaskId(),
                        relation.getProcessId()
                );
                weChatSendMessageDto.setUrl(url);

                weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
                String openId = userOpenIdMap.get(courseAdjust.getExchangeTeacherId());
                if(openId != null && !"".equals(openId)){
                    weChatSendMessageDto.setUserId(openId);
                    weChatService.sendTemplateMessage(weChatSendMessageDto);
                }
            }
            String url = StrUtil.format(
                    "{}/xjrsoft/pages/workflow/look?processId={}&type=my",
                    commonPropertiesConfig.getDomainApp(),
                    relation.getProcessId()
            );
            weChatSendMessageDto.setUrl(url);
            weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
            String openId = userOpenIdMap.get(courseAdjust.getUserId());
            if(openId != null && !"".equals(openId)){
                weChatSendMessageDto.setUserId(openId);
                weChatService.sendTemplateMessage(weChatSendMessageDto);
            }
            String processId = relation.getProcessId();

            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
            Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
            Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
            //获取到当前活动的实例
            ActivityInstance activityInstance = runtimeService.getActivityInstance(task.getProcessInstanceId());

            String message = "    因课表更新之后当前课程已发生变更，该流程已内部终止，如还需调/顶课，请重新发起调/顶课流程";
            //先停止当前活动示例  然后  关闭流程
            runtimeService.createProcessInstanceModification(task.getProcessInstanceId())
                    .cancelActivityInstance(activityInstance.getId())
                    .cancelAllForActivity(activityInstance.getId())
                    .setAnnotation("因课表更新之后当前课程已发生变更，该流程已内部终止")
                    .execute();

            //新增流程发起流程记录
            WorkflowRecord record = new WorkflowRecord();
            record.setNodeId(task.getId());
            record.setNodeName(task.getName());
            record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
            record.setProcessId(task.getProcessInstanceId());
            record.setSchemaId(schemaId);
            record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
            record.setRecordTime(LocalDateTime.now());
            record.setWorkflowApproveType(WorkflowApproveType.FINISH.getCode());

            record.setMessage(message);

            workflowRecordService.save(record);

            //新增流程发起流程记录
            XjrWorkflowOperateRecord xjrWorkflowOperateRecord = new XjrWorkflowOperateRecord();
            xjrWorkflowOperateRecord.setNodeId(task.getId());
            xjrWorkflowOperateRecord.setNodeName(task.getName());
            xjrWorkflowOperateRecord.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
            xjrWorkflowOperateRecord.setProcessId(task.getProcessInstanceId());
            xjrWorkflowOperateRecord.setSchemaId(schemaId);
            xjrWorkflowOperateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
            xjrWorkflowOperateRecord.setRecordTime(LocalDateTime.now());
            xjrWorkflowOperateRecord.setUsageScenario(1);


            xjrWorkflowOperateRecord.setOperateInfo(message);
            xjrWorkflowOperateRecordMapper.insert(xjrWorkflowOperateRecord);


            Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
            historicProcessInstance.ifPresent(item -> {
                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
                    setProcessId(processId);
                    setCurrentState(item.getState());
                    setStartTime(item.getStartTime());
                    setEndTime(item.getEndTime());
                }});
            });
        }
    }


    /**
     * 挂起未通过的流程
     */
    List<String> suspendedCourseAdjust(List<BaseClass> classList, String startDate, String endDate) {
        List<Long> classIds = classList.stream().map(BaseClass::getId).collect(Collectors.toList());
        List<CourseTableBak> bakList = courseTableBakService.list(
                new QueryWrapper<CourseTableBak>().lambda()
                        .in(CourseTableBak::getClassId, classIds)
                        .between(CourseTableBak::getScheduleDate, startDate, endDate)
        );
        Set<Long> courseAdjustIdSet = bakList.stream().map(CourseTableBak::getWfCourseAdjustId).collect(Collectors.toSet());

        List<Long> courseAdjustIds = new ArrayList<>(courseAdjustIdSet);
        List<WorkflowFormRelation> list = formRelationService.list(
                new MPJLambdaWrapper<WorkflowFormRelation>()
                        .select(WorkflowFormRelation::getId)
                        .select(WorkflowFormRelation.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowFormRelation.class).contains(x.getProperty()))
                        .innerJoin(WfCourseAdjust.class, WfCourseAdjust::getId, WorkflowFormRelation::getFormKeyValue)
                        .between(WfCourseAdjust::getAdjustDate, startDate, endDate)
                        .in(!courseAdjustIds.isEmpty(), WfCourseAdjust::getId, courseAdjustIds)
                        .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
        );
        List<String> processIds = new ArrayList<>();
        for (WorkflowFormRelation relation : list) {
            String processId = relation.getProcessId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
            Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
            Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
            //新增流程发起流程记录
            WorkflowRecord record = new WorkflowRecord();
            record.setNodeId(task.getId());
            record.setNodeName(task.getName());
            record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
            record.setProcessId(task.getProcessInstanceId());
            record.setSchemaId(schemaId);
            record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
            record.setRecordTime(LocalDateTime.now());

            if (processInstance.isSuspended()) {
                runtimeService.activateProcessInstanceById(relation.getProcessId());
                //[操作人名称] 将流程恢复
                record.setMessage("课表同步成功，流程恢复");
            } else {
                runtimeService.suspendProcessInstanceById(relation.getProcessId());
                //[操作人名称] 将流程挂起
                record.setMessage("课表更新中，暂停流程审核，请等待课表更新完成之后进行审核");
            }
            workflowRecordService.save(record);
            Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
            historicProcessInstance.ifPresent(item -> {
                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
                    setProcessId(processId);
                    setCurrentState(item.getState());
                    setStartTime(item.getStartTime());
                    setEndTime(item.getEndTime());
                }});
            });

            processIds.add(relation.getProcessId());
        }
        return processIds;
    }

    /**
     * 将挂起的流程恢复
     */
    void restoreCourseAdjust(List<String> processIds){
        for (String processId : processIds) {
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processId).list();
            Task task = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processId)).findFirst().orElse(new TaskEntity());
            Long schemaId = Convert.toLong(taskService.getVariable(task.getId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
            //新增流程发起流程记录
            WorkflowRecord record = new WorkflowRecord();
            record.setNodeId(task.getId());
            record.setNodeName(task.getName());
            record.setNodeType(WorkflowConstant.USER_TASK_TYPE_NAME);
            record.setProcessId(task.getProcessInstanceId());
            record.setSchemaId(schemaId);
            record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
            record.setRecordTime(LocalDateTime.now());
            record.setMessage("课表同步成功，流程恢复");
            workflowRecordService.save(record);
            runtimeService.activateProcessInstanceById(processId);

            Optional<HistoricProcessInstance> historicProcessInstance = workflowExecuteService.getHistoricProcessInstance(processId);
            historicProcessInstance.ifPresent(item -> {
                formRelationService.updateCurrentState(new WorkflowFormRelation() {{
                    setProcessId(processId);
                    setCurrentState(item.getState());
                    setStartTime(item.getStartTime());
                    setEndTime(item.getEndTime());
                }});
            });
        }
    }
}