package com.qmth.distributed.print.business.activiti.custom.listener;

import com.google.gson.Gson;
import com.qmth.distributed.print.business.bean.flow.CustomFlowVarDto;
import com.qmth.distributed.print.business.bean.result.FlowTaskResult;
import com.qmth.distributed.print.business.entity.ExamTask;
import com.qmth.distributed.print.business.entity.TFFlowLog;
import com.qmth.distributed.print.business.enums.CustomFlowMultipleUserApproveTypeEnum;
import com.qmth.distributed.print.business.enums.MessageEnum;
import com.qmth.distributed.print.business.service.ActivitiService;
import com.qmth.distributed.print.business.service.BasicMessageService;
import com.qmth.distributed.print.business.service.PrintCommonService;
import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.FlowApproveOperationEnum;
import com.qmth.teachcloud.common.enums.TFCustomTypeEnum;
import com.qmth.teachcloud.common.service.SysUserService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiProcessStartedEvent;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 全局监听
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2022/2/8
 */
@Component
public class ProcessEventListener implements ActivitiEventListener, Serializable {
    private final static Logger log = LoggerFactory.getLogger(ProcessEventListener.class);

    @Override
    public void onEvent(ActivitiEvent event) {
        switch (event.getType()) {
            case PROCESS_STARTED:
                // 流程启动
//                log.info("流程启动_PROCESS_STARTED:ProcessInstanceId:{},ExecutionId:{},ProcessDefinitionId:{}", event.getProcessInstanceId(), event.getExecutionId(), event.getProcessDefinitionId());
                BasicMessageService basicMessageService = SpringContextHolder.getBean(BasicMessageService.class);
                ActivitiProcessStartedEvent activitiProcessStartedEvent = (ActivitiProcessStartedEvent) event;
                Map<String, Object> map = activitiProcessStartedEvent.getVariables();
                Long objectId = (Long) map.get(SystemConstant.OBJECT_ID);
                TFCustomTypeEnum flowType = (TFCustomTypeEnum) map.get(SystemConstant.FLOW_TYPE);
                Object o = map.get(SystemConstant.OBJECT_DATA);
                Boolean flowSubmit = (Boolean) map.get(SystemConstant.FLOW_SUBMIT);
                //发送命题待审批短信
                if (Objects.nonNull(objectId) && Objects.nonNull(flowType) && Objects.nonNull(o) && Objects.nonNull(flowSubmit) && flowSubmit) {
                    if (flowType == TFCustomTypeEnum.ELECTRON_FLOW && o instanceof ExamTask) {
                        basicMessageService.sendNoticeTaskCreate((ExamTask) o);
                    }
                }
                break;
            case PROCESS_COMPLETED:
                // 流程结束
//                log.info("流程结束_PROCESS_COMPLETED:ProcessInstanceId:{},ExecutionId:{},ProcessDefinitionId:{}", event.getProcessInstanceId(), event.getExecutionId(), event.getProcessDefinitionId());
                HistoryService historyService = SpringContextHolder.getBean(HistoryService.class);
                SysUserService sysUserService = SpringContextHolder.getBean(SysUserService.class);
                PrintCommonService printCommonService = SpringContextHolder.getBean(PrintCommonService.class);

                List<HistoricVariableInstance> historicVariableInstanceList = historyService.createHistoricVariableInstanceQuery().processInstanceId(event.getProcessInstanceId()).list();
                if (Objects.nonNull(historicVariableInstanceList) && historicVariableInstanceList.size() > 0) {
                    TFFlowLog tfFlowLog = null;
                    Object object = null;
                    for (HistoricVariableInstance h : historicVariableInstanceList) {
                        if (Objects.equals(h.getVariableName(), SystemConstant.APPROVE_TF_FLOW_LOG)) {
                            tfFlowLog = (TFFlowLog) h.getValue();
                            Optional.ofNullable(tfFlowLog).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程审批日志为空"));
                        } else if (Objects.equals(h.getVariableName(), SystemConstant.OBJECT_DATA)) {
                            object = h.getValue();
                            Optional.ofNullable(object).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("实体数据为空"));
                        }
                        if (Objects.nonNull(object) && Objects.nonNull(tfFlowLog)) {
                            break;
                        }
                    }
                    if (Objects.nonNull(tfFlowLog.getObjectTable())) {
                        if (Objects.equals(tfFlowLog.getObjectTable(), TFCustomTypeEnum.ELECTRON_FLOW.getTable())) {//如果是命题任务交卷
                            //取命题老师ID
                            SysUser sysUser = sysUserService.getById(((ExamTask) object).getUserId());
                            try {
                                printCommonService.checkData(((ExamTask) object).getSchoolId(), ((ExamTask) object).getCourseCode(), ((ExamTask) object).getPaperNumber(), sysUser);
                            } catch (IOException e) {
                                throw ExceptionResultEnum.ERROR.exception("生成pdf失败");
                            }
                        }
                    }
                }
                break;
            case TASK_COMPLETED:
                // 任务被完成了。它会在ENTITY_DELETE事件之前触发。当任务是流程一部分时，事件会在流程继续运行之前， 后续事件将是ACTIVITY_COMPLETE，对应着完成任务的节点。
//                log.info("流程任务完成_TASK_COMPLETED:ProcessInstanceId:{},ExecutionId:{},ProcessDefinitionId:{}", event.getProcessInstanceId(), event.getExecutionId(), event.getProcessDefinitionId());
                TaskService taskService = SpringContextHolder.getBean(TaskService.class);
                sysUserService = SpringContextHolder.getBean(SysUserService.class);
                basicMessageService = SpringContextHolder.getBean(BasicMessageService.class);
                ActivitiService activitiService = SpringContextHolder.getBean(ActivitiService.class);

                Task task = taskService.createTaskQuery().executionId(event.getExecutionId()).singleResult();
                if (Objects.nonNull(task)) {
                    TFFlowLog tfFlowLog = (TFFlowLog) taskService.getVariable(task.getId(), SystemConstant.APPROVE_TF_FLOW_LOG);
                    Optional.ofNullable(tfFlowLog).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程审批日志为空"));
                    o = taskService.getVariable(task.getId(), SystemConstant.OBJECT_DATA);
                    Optional.ofNullable(o).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("实体数据为空"));
                    Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) taskService.getVariable(task.getId(), SystemConstant.AGGINESS_MAP);
                    Optional.ofNullable(agginessMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程审批数据为空"));
                    Map<String, FlowTaskResult> setupMap = (Map<String, FlowTaskResult>) taskService.getVariable(task.getId(), SystemConstant.SETUP_MAP);
                    Optional.ofNullable(setupMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程审批步骤数据为空"));

                    if (tfFlowLog.getApproveOperation() != FlowApproveOperationEnum.SUBMIT
                            && tfFlowLog.getApproveOperation() != FlowApproveOperationEnum.END
                            && tfFlowLog.getApproveOperation() != FlowApproveOperationEnum.FINISH) {
                        if (Objects.nonNull(tfFlowLog.getPendApproveId())) {
                            String[] strs = tfFlowLog.getPendApproveId().split(",");
                            List<Long> userIds = new ArrayList<>();
                            for (String s : strs) {
                                userIds.add(SystemConstant.convertIdToLong(s.trim()));
                            }
                            Gson gson = new Gson();
                            List<ApproveUserResult> nextApproverPeopleList = sysUserService.findByIdsForResult(userIds);
                            if (Objects.nonNull(nextApproverPeopleList) && nextApproverPeopleList.size() > 0 && Objects.nonNull(tfFlowLog.getApproveUserApproveType()) && tfFlowLog.getApproveUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.ORDER) {
                                nextApproverPeopleList.removeAll(nextApproverPeopleList.subList(1, nextApproverPeopleList.size() - 0));
                            }

                            if (Objects.nonNull(nextApproverPeopleList) && tfFlowLog.getApproveOperation() == FlowApproveOperationEnum.APPROVE) {
                                List<ApproveUserResult> copyUsersList = null;
                                FlowTaskResult nextFlowTaskResult = null;
                                FlowTaskResult currFlowTaskResult = gson.fromJson(gson.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
                                int currSetup = currFlowTaskResult.getSetup().intValue();
                                currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;

                                nextFlowTaskResult = activitiService.getNextFlowTaskResult(setupMap, gson, currSetup, nextFlowTaskResult);
                                CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
                                if (Objects.nonNull(customFlowVarDto) && Objects.nonNull(customFlowVarDto.getCopyForUserIds()) && customFlowVarDto.getCopyForUserIds().size() > 0) {
                                    Set<String> copyUserSet = new LinkedHashSet(customFlowVarDto.getCopyForUserIds());
                                    copyUsersList = sysUserService.findByIdsForResult(copyUserSet.stream().map(s -> SystemConstant.convertIdToLong(s)).collect(Collectors.toList()));
                                }

                                //如果不是并行会签，则每个节点都发
                                if (Objects.nonNull(tfFlowLog.getApproveUserApproveType()) && tfFlowLog.getApproveUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.ORDER) {
                                    if (Objects.nonNull(o) && o instanceof ExamTask) {
                                        basicMessageService.sendNoticeTaskAuditFlow((ExamTask) o, nextApproverPeopleList, MessageEnum.NOTICE_OF_AUDIT_CREATED);
                                        //抄送短信
                                        if (Objects.nonNull(copyUsersList) && copyUsersList.size() > 0) {
                                            basicMessageService.sendNoticeAuditCopyUser((ExamTask) o, copyUsersList, nextApproverPeopleList.get(0).getRealName(), MessageEnum.NOTICE_OF_AUDIT_COPY_USER);
                                        }
                                    }
                                } else {
                                    if (Objects.isNull(tfFlowLog.getApproveMultiSetup())) {
                                        if (Objects.nonNull(o) && o instanceof ExamTask) {
                                            basicMessageService.sendNoticeTaskAuditFlow((ExamTask) o, nextApproverPeopleList, MessageEnum.NOTICE_OF_AUDIT_CREATED);
                                        }
                                        //抄送短信
                                        if (Objects.nonNull(copyUsersList) && copyUsersList.size() > 0) {
                                            basicMessageService.sendNoticeAuditCopyUser((ExamTask) o, copyUsersList, nextApproverPeopleList.stream().map(s -> s.getRealName()).collect(Collectors.toList()).toString().replaceAll("\\[", "").replaceAll("\\]", "").trim(), MessageEnum.NOTICE_OF_AUDIT_COPY_USER);
                                        }
                                    }
                                }
                            } else if (Objects.nonNull(nextApproverPeopleList) && (tfFlowLog.getApproveOperation() == FlowApproveOperationEnum.REJECT
                                    || tfFlowLog.getApproveOperation() == FlowApproveOperationEnum.CANCEL)) {
                                if (Objects.nonNull(o) && o instanceof ExamTask) {
                                    basicMessageService.sendNoticeTaskAuditFlow((ExamTask) o, nextApproverPeopleList, MessageEnum.NOTICE_OF_AUDIT_REJECT);
                                }
                            }
                        }
                    }
                }
                break;
            default:
//                log.info("default->type:{},ProcessInstanceId:{},ExecutionId:{},ProcessDefinitionId:{}", event.getType(), event.getProcessInstanceId(), event.getExecutionId(), event.getProcessDefinitionId());
                break;
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }
}
