package com.yunzhupaas.flowable.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.ImmutableList;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.constant.PermissionConst;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.*;
import com.yunzhupaas.flowable.enums.*;
import com.yunzhupaas.flowable.model.flowable.*;
import com.yunzhupaas.flowable.model.message.FlowMsgModel;
import com.yunzhupaas.flowable.model.record.NodeRecordModel;
import com.yunzhupaas.flowable.model.task.*;
import com.yunzhupaas.flowable.model.templatejson.FlowFormModel;
import com.yunzhupaas.flowable.model.templatejson.FlowParamModel;
import com.yunzhupaas.flowable.model.templatenode.FlowErrorModel;
import com.yunzhupaas.flowable.model.templatenode.nodejson.*;
import com.yunzhupaas.flowable.model.util.FlowConstant;
import com.yunzhupaas.flowable.model.util.FlowContextHolder;
import com.yunzhupaas.flowable.model.util.FlowNature;
import com.yunzhupaas.flowable.service.*;
import com.yunzhupaas.permission.entity.OrganizeEntity;
import com.yunzhupaas.permission.entity.RoleEntity;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.permission.entity.UserRelationEntity;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/22 16:46
 */
@Component
public class TaskUtil {
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private LaunchUserService launchUserService;
    @Autowired
    private CandidatesService candidatesService;
    @Autowired
    private RecordService recordService;
    @Autowired
    private MsgUtil msgUtil;
    @Autowired
    private FlowAbleUrl flowAbleUrl;
    @Autowired
    private TaskService taskService;
    @Autowired
    private OperatorService operatorService;
    @Autowired
    private OperatorUtil operatorUtil;
    @Autowired
    private TemplateService templateService;
    @Autowired
    private TemplateJsonService templateJsonService;
    @Autowired
    private TemplateNodeService templateNodeService;
    @Autowired
    private ConditionService conditionService;
    @Autowired
    private TaskLineService taskLineService;
    @Autowired
    private RevokeService revokeService;
    @Autowired
    private NodeRecordService nodeRecordService;
    @Autowired
    private RecordUtil recordUtil;
    @Autowired
    private SubtaskDataService subtaskDataService;

    // 提交撤销流程
    public void submitOfRevoke(FlowModel flowModel) throws Exception {
        TaskEntity task = flowModel.getTaskEntity();
        List<TaskLineEntity> lineList = taskLineService.getList(task.getId());
        if (CollectionUtil.isEmpty(lineList)) {
            throw new WorkFlowException("无法撤销");
        }
        // 委托人的处理
        UserInfo userInfo = flowModel.getUserInfo();
        String creatorUserId = task.getCreatorUserId();
        String delegateUserId = task.getDelegateUserId();
        boolean isDelegate = !ObjectUtil.equals(userInfo.getUserId(), creatorUserId);
        if (isDelegate) {
            if (StringUtil.isNotEmpty(delegateUserId)) {
                String token = AuthUtil.loginTempUser(task.getCreatorUserId(), UserProvider.getUser().getTenantId());
                userInfo = UserProvider.getUser(token);
                flowModel.setUserInfo(userInfo);
            }
        }

        Map<String, Object> variables = new HashMap<>();
        for (TaskLineEntity condition : lineList) {
            variables.put(condition.getLineKey(), Boolean.valueOf(condition.getLineValue()));
        }

        TaskEntity entity = new TaskEntity();
        entity.setId(RandomUtil.uuId());
        entity.setType(1);
        entity.setUrgent(task.getUrgent());
        entity.setCreatorUserId(task.getCreatorUserId());
        entity.setStartTime(new Date());
        entity.setCreatorTime(new Date());
        entity.setFullName(task.getFullName() + "的撤销申请");
        entity.setFlowCategory(task.getFlowCategory());
        entity.setFlowCode(task.getFlowCode());
        entity.setFlowName(task.getFlowName());
        entity.setFlowVersion(task.getFlowVersion());
        entity.setFlowId(task.getFlowId());
        entity.setTemplateId(task.getTemplateId());
        entity.setParentId(task.getParentId());
        entity.setFlowType(task.getFlowType());
        entity.setStatus(TaskStatusEnum.RUNNING.getCode());
        entity.setEngineType(task.getEngineType());
        if (isDelegate) {
            entity.setDelegateUserId(delegateUserId);
        }

        TemplateJsonEntity jsonEntity = templateJsonService.getInfo(task.getFlowId());
        String instanceId = flowAbleUrl.startInstance(jsonEntity.getFlowableId(), variables);
        entity.setInstanceId(instanceId);

        if (taskService.save(entity)) {
            List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
            TemplateNodeEntity nodeEntity = nodeEntityList.stream()
                    .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst()
                    .orElse(new TemplateNodeEntity());
            NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
            // 记录
            FlowMethod method = new FlowMethod();
            method.setFlowModel(flowModel);
            method.setType(RecordEnum.submit.getCode());
            OperatorEntity operatorEntity = new OperatorEntity();
            operatorEntity.setNodeCode(nodeEntity.getNodeCode());
            operatorEntity.setNodeName(nodeModel.getNodeName());
            operatorEntity.setTaskId(entity.getId());
            operatorEntity.setHandleId(entity.getCreatorUserId());
            if (StringUtil.isNotBlank(flowModel.getUserId())) {
                method.setHandId(flowModel.getUserId());
            }
            operatorEntity.setHandleTime(entity.getStartTime());
            method.setOperatorEntity(operatorEntity);
            recordUtil.createRecord(method);
            // 节点记录
            NodeRecordModel nodeRecordModel = new NodeRecordModel();
            nodeRecordModel.setTaskId(entity.getId());
            nodeRecordModel.setNodeCode(nodeEntity.getNodeCode());
            nodeRecordModel.setNodeName(nodeModel.getNodeName());
            nodeRecordModel.setNodeStatus(1);
            nodeRecordService.create(nodeRecordModel);
            // 保存到撤销表
            RevokeEntity revokeEntity = new RevokeEntity();
            revokeEntity.setId(RandomUtil.uuId());
            revokeEntity.setTaskId(task.getId());
            revokeEntity.setRevokeTaskId(entity.getId());

            RevokeFormDataModel model = new RevokeFormDataModel();
            String billNumber = serviceUtil.getBillNumber();
            model.setBillRule(billNumber);
            model.setHandleOpinion(flowModel.getHandleOpinion());
            Date date = new Date();
            model.setCreatorTime(date.getTime());
            model.setRevokeTaskId(task.getId());
            model.setRevokeTaskName(task.getFullName());
            String str = JsonUtil.getObjectToString(model);
            revokeEntity.setFormData(str);
            revokeService.save(revokeEntity);
            // 处理撤销经办
            FlowMethod flowMethod = new FlowMethod();
            flowMethod.setFlowModel(flowModel);
            flowMethod.setTaskId(task.getId());
            flowMethod.setTaskEntity(entity);
            operatorUtil.handleRevokeOperator(flowMethod);
            // 自动审批
            FlowModel revokeModel = JsonUtil.getJsonToBean(flowModel, FlowModel.class);
            revokeModel.setTaskEntity(entity);
            operatorUtil.autoAudit(revokeModel);
            // 判断结束
            flowModel.setTaskEntity(entity);
            if (this.isFinished(flowModel)) {
                this.endRevoke(task);
            }
        }
    }

    public void endRevoke(TaskEntity task) {
        QueryWrapper<TaskEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(TaskEntity::getParentId, task.getId());
        List<TaskEntity> subTaskList = taskService.list(wrapper);
        // 变更子流程任务状态
        if (CollectionUtil.isNotEmpty(subTaskList)) {
            for (TaskEntity subTask : subTaskList) {
                subTask.setStatus(TaskStatusEnum.REVOKED.getCode());
            }
            taskService.updateBatchById(subTaskList);
        }
        task.setStatus(TaskStatusEnum.REVOKED.getCode());
        taskService.updateById(task);
    }

    // 更新当前节点
    public void updateCurrentNode(List<FlowableTaskModel> taskModelList, Map<String, NodeModel> nodes,
            TaskEntity taskEntity) {
        List<String> currentNodeList = new ArrayList<>();
        List<String> currentNodeNameList = new ArrayList<>();

        List<String> nodeTypes = ImmutableList.of(NodeEnum.approver.getType(), NodeEnum.subFlow.getType(),
                NodeEnum.processing.getType());
        for (FlowableTaskModel model : taskModelList) {
            NodeModel nodeModel = nodes.get(model.getTaskKey());
            if (null != nodeModel && nodeTypes.contains(nodeModel.getType())) {
                currentNodeList.add(nodeModel.getNodeId());
                currentNodeNameList.add(nodeModel.getNodeName());
            }
        }
        if (CollectionUtil.isNotEmpty(currentNodeList)) {
            // 更新任务的当前节点信息
            taskEntity.setCurrentNodeName(String.join(",", currentNodeNameList));
            taskEntity.setCurrentNodeCode(String.join(",", currentNodeList));
            taskService.updateById(taskEntity);
        }
    }

    // 拒绝结束流程
    public void handleEndTask(FlowMethod flowMethod) throws Exception {
        OperatorEntity operator = flowMethod.getOperatorEntity();
        List<CirculateEntity> circulateList = flowMethod.getCirculateList();
        FlowModel flowModel = flowMethod.getFlowModel();
        TaskEntity taskEntity = flowModel.getTaskEntity();
        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();

        // 触发
        if (!flowMethod.getIsRevoke()) {
            flowModel.setAction(2);
            flowModel.setRejectTrigger(true);
            operatorUtil.handleTrigger(operator, flowModel);
        }

        // 直接结束流程
        flowMethod.setState(TaskStatusEnum.REJECTED.getCode());
        this.endTask(flowMethod);
        // 处理当前节点
        flowModel.setFinishFlag(false);
        List<String> codes = Arrays.stream(taskEntity.getCurrentNodeCode().split(",")).collect(Collectors.toList());
        codes.remove(operator.getNodeCode());
        taskEntity.setCurrentNodeCode(String.join(",", codes));

        // 节点记录
        NodeRecordModel nodeRecordModel = new NodeRecordModel();
        nodeRecordModel.setTaskId(operator.getTaskId());
        nodeRecordModel.setNodeId(operator.getNodeId());
        nodeRecordModel.setNodeCode(operator.getNodeCode());
        nodeRecordModel.setNodeName(operator.getNodeName());
        nodeRecordModel.setNodeStatus(3);
        nodeRecordService.create(nodeRecordModel);

        FlowMsgModel flowMsgModel = new FlowMsgModel();
        flowMsgModel.setNodeList(nodeEntityList);
        flowMsgModel.setFlowModel(flowModel);
        flowMsgModel.setTaskEntity(taskEntity);
        flowMsgModel.setNodeCode(operator.getNodeCode());
        flowMsgModel.setWait(false);
        flowMsgModel.setReject(true);
        flowMsgModel.setCopy(true);
        List<OperatorEntity> operatorList = new ArrayList<>();
        OperatorEntity entity = new OperatorEntity();
        entity.setNodeCode(operator.getNodeCode());
        entity.setHandleId(taskEntity.getCreatorUserId());
        operatorList.add(entity);
        flowMsgModel.setOperatorList(operatorList);
        flowMsgModel.setCirculateList(circulateList);
        flowMsgModel.setFormData(FlowContextHolder.getAllData());
        msgUtil.message(flowMsgModel);

        this.isFinished(flowModel);
    }

    public List<TaskEntity> getTaskByTemplate(String templateId) {
        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskEntity::getTemplateId, templateId);
        return taskService.list(queryWrapper);
    }

    // 判断用户是否有发起权限
    public void checkLaunchPermission(String userId, TemplateEntity template) throws WorkFlowException {
        if (null != template && ObjectUtil.equals(template.getVisibleType(), 2)) {
            if (serviceUtil.isCommonUser(userId)) {
                List<String> flowIds = serviceUtil.getLaunchPermission(userId);
                if (!flowIds.contains(template.getId())) {
                    throw new WorkFlowException(MsgCode.WF029.get());
                }
            }
        }
    }

    public void updateGlobalParam(TaskEntity taskEntity, NodeModel nodeModel, NodeModel global,
            Map<String, Object> formData) throws WorkFlowException {
        this.getGlobalParam(taskEntity, nodeModel, global, formData);
        taskService.updateById(taskEntity);
    }

    public void getGlobalParam(TaskEntity taskEntity, NodeModel nodeModel, NodeModel global,
            Map<String, Object> formData) throws WorkFlowException {
        List<FlowParamModel> paramModelList = global.getGlobalParameterList();
        if (CollectionUtil.isEmpty(paramModelList)) {
            return;
        }
        formData = formData == null ? new HashMap<>() : formData;
        List<TemplateJsonModel> list = new ArrayList<>();
        for (GroupsModel group : nodeModel.getParameterList()) {
            TemplateJsonModel model = new TemplateJsonModel();
            model.setField(group.getField());
            model.setSourceType(group.getFieldValueType() == 3 ? 4 : group.getFieldValueType());
            model.setRelationField(String.valueOf(group.getFieldValue()));
            model.setMsgTemplateId(group.getField());
            list.add(model);
        }
        Map<String, Object> taskMap = taskEntity.getGlobalParameter() != null
                ? JsonUtil.stringToMap(taskEntity.getGlobalParameter())
                : new HashMap<>();
        if (CollectionUtil.isEmpty(taskMap)) {
            for (FlowParamModel model : paramModelList) {
                if (model.getDefaultValue() != null) {
                    taskMap.put(model.getFieldName(), model.getDefaultValue());
                }
            }
        }
        RecordEntity record = new RecordEntity();
        record.setNodeCode(nodeModel.getNodeId());
        // UserEntity createUser =
        // serviceUtil.getUserInfo(taskEntity.getCreatorUserId());
        // UserEntity delegate = StringUtil.isNotEmpty(taskEntity.getDelegateUserId()) ?
        // serviceUtil.getUserInfo(taskEntity.getDelegateUserId()) : null;
        Map<String, String> map = msgUtil.parameterMap(formData, list, record, taskEntity);
        taskMap.putAll(map);
        for (FlowParamModel model : paramModelList) {
            if (ObjectUtil.equals(model.getDataType(), "datetime")) {
                String fieldName = model.getFieldName();
                Long longVal = Long.valueOf(String.valueOf(taskMap.get(fieldName)));
                taskMap.put(fieldName, longVal);
            }
        }
        taskEntity.setGlobalParameter(JsonUtil.getObjectToString(taskMap));
    }

    /**
     * 根据主键集合获取任务实体
     *
     * @param ids 主键集合
     */
    public List<TaskEntity> getOrderStaList(List<String> ids) {
        List<TaskEntity> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ids)) {
            QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(TaskEntity::getId, ids);
            list = taskService.list(queryWrapper);
        }
        return list;
    }

    /**
     * 设置参数
     *
     * @param taskId    任务主键
     * @param flowModel 参数
     */
    public void setFlowModel(String taskId, FlowModel flowModel) throws WorkFlowException {
        if (flowModel.getUserInfo() == null) {
            flowModel.setUserInfo(UserProvider.getUser());
        }
        TaskEntity taskEntity = taskService.getInfo(taskId);
        if (null == taskEntity) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        TemplateJsonEntity jsonEntity = templateJsonService.getInfo(taskEntity.getFlowId());
        flowModel.setJsonEntity(jsonEntity);
        flowModel.setDeploymentId(jsonEntity.getFlowableId());
        flowModel.setTaskEntity(taskEntity);
        List<TemplateNodeEntity> nodeEntityList = templateNodeService.getList(taskEntity.getFlowId());
        flowModel.setNodeEntityList(nodeEntityList);
        Map<String, NodeModel> nodes = new HashMap<>();
        for (TemplateNodeEntity nodeEntity : nodeEntityList) {
            nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
        }
        flowModel.setNodes(nodes);
    }

    /**
     * 依次审批的排序
     *
     * @param userIds   用户主键集合
     * @param nodeModel 节点属性
     */
    public List<String> improperSort(List<String> userIds, NodeModel nodeModel) {
        List<String> list = new ArrayList<>();
        List<String> sortList = nodeModel.getApproversSortList();
        if (sortList.isEmpty()) {
            return userIds;
        }
        for (String id : sortList) {
            List<String> collect = userIds.stream().filter(id::contains).collect(Collectors.toList());
            list.addAll(collect);
        }
        return list.stream().distinct().collect(Collectors.toList());
    }

    // 结束任务
    public void endTask(FlowMethod flowMethod) throws Exception {
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        Integer state = flowMethod.getState();
        taskEntity.setStatus(state);
        taskEntity.setEndTime(new Date());
        if (taskService.updateById(taskEntity)) {
            flowMethod.setTaskId(taskEntity.getId());
            flowMethod.setNodeCode(null);
            operatorUtil.endOperator(flowMethod);
            flowAbleUrl.deleteInstance(taskEntity.getInstanceId(), "reject");
        }
    }

    /**
     * 判断任务是否结束
     *
     * @param flowModel 参数
     */
    public boolean isFinished(FlowModel flowModel) throws Exception {
        TaskEntity taskEntity = flowModel.getTaskEntity();
        if (null == taskEntity.getId()) {
            return false;
        }
        TaskEntity task = taskService.getById(taskEntity.getId());
        if (null != task && ObjectUtil.equals(task.getStatus(), TaskStatusEnum.CANCEL.getCode())) {
            return false;
        }
        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
        String instanceId = taskEntity.getInstanceId();
        boolean flag;
        FlowableInstanceModel instance = flowAbleUrl.getInstance(instanceId);
        if (null != instance && null != instance.getEndTime()) {
            flag = true;
        } else {
            List<String> historicEnd = flowAbleUrl.getHistoricEnd(instanceId);
            flag = CollectionUtil.isNotEmpty(historicEnd);
        }
        if (flag) {
            TemplateNodeEntity endNodeEntity = nodeEntityList.stream()
                    .filter(e -> StringUtil.equals(e.getNodeType(), NodeEnum.end.getType())).findFirst().orElse(null);
            if (null != endNodeEntity) {
                if (flowModel.getFinishFlag()) {
                    taskEntity.setCurrentNodeCode(FlowNature.END_CODE);
                    taskEntity.setCurrentNodeName(FlowNature.END_NAME);
                }
                Integer status = flowModel.getHandleStatus().equals(FlowNature.AuditCompletion)
                        ? TaskStatusEnum.PASSED.getCode()
                        : TaskStatusEnum.REJECTED.getCode();
                taskEntity.setStatus(status);
                taskEntity.setEndTime(new Date());
                if (taskService.updateById(taskEntity)) {
                    this.subFlowOfEnd(flowModel);
                    flowModel.setEventStatus(2);
                    operatorUtil.addEvent(flowModel);
                    // 发送结束消息
                    FlowMsgModel flowMsgModel = new FlowMsgModel();
                    flowMsgModel.setNodeList(nodeEntityList);
                    flowMsgModel.setTaskEntity(taskEntity);
                    flowMsgModel.setFlowModel(flowModel);
                    flowMsgModel.setEnd(true);
                    flowMsgModel.setFormData(FlowContextHolder.getAllData());
                    msgUtil.message(flowMsgModel);
                    return true;
                }
            }
        }
        return false;
    }

    // 判断能否归档
    public AuditModel getAuditModel(String taskId, FlowModel flowModel, OperatorEntity operator) {
        TaskEntity task = taskService.getById(taskId);
        AuditModel model = new AuditModel();
        if (operator != null && ObjectUtil.equals(operator.getStatus(), OperatorStateEnum.Revoke.getCode())) {
            return model;
        }
        if (task != null) {
            model.setTaskId(taskId);
            if (task.getEndTime() != null) {
                NodeModel global = flowModel.getNodes().get(NodeEnum.global.getType());
                FileConfig config = global.getFileConfig();
                if (config.getOn() && StringUtil.isNotBlank(config.getTemplateId())) {
                    model.setIsEnd(true);
                }
            }
        }
        return model;
    }

    // 子流程结束 要处理的事情
    public void subFlowOfEnd(FlowModel flowModel) throws Exception {
        TaskEntity taskEntity = flowModel.getTaskEntity();
        if (StringUtil.equals("0", taskEntity.getParentId())) {
            return;
        }
        // 获取父级节点集合
        TaskEntity parentTask = taskService.getInfo(taskEntity.getParentId());
        if (null == parentTask) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        TemplateJsonEntity jsonEntity = templateJsonService.getById(parentTask.getFlowId());
        String deploymentId = jsonEntity.getFlowableId();
        List<TemplateNodeEntity> parentNodeList = templateNodeService.getList(parentTask.getFlowId());

        String subCode = taskEntity.getSubCode();
        SubParameterModel subParameter = JsonUtil.getJsonToBean(taskEntity.getSubParameter(), SubParameterModel.class);
        String flowableTaskId = subParameter.getNodeId();
        String parentCode = subParameter.getParentCode();

        TemplateNodeEntity parentNode = parentNodeList.stream()
                .filter(e -> e.getNodeCode().equals(parentCode)).findFirst().orElse(new TemplateNodeEntity());
        TemplateNodeEntity subNode = parentNodeList.stream()
                .filter(e -> e.getNodeCode().equals(subCode)).findFirst().orElse(new TemplateNodeEntity());
        NodeModel nodeModel = JsonUtil.getJsonToBean(subNode.getNodeJson(), NodeModel.class);
        if (nodeModel == null) {
            return;
        }
        // 判断是否依次创建，存在依次创建的子流程数据，则发起子流程
        if (ObjectUtil.equals(nodeModel.getCreateRule(), 1)) {
            List<SubtaskDataEntity> list = subtaskDataService.getList(taskEntity.getParentId(), subCode);
            if (CollectionUtil.isNotEmpty(list)) {
                SubtaskDataEntity subtaskData = list.get(0);
                FlowModel model = JsonUtil.getJsonToBean(subtaskData.getSubtaskJson(), FlowModel.class);
                taskService.batchSaveOrSubmit(model);
                subtaskDataService.removeById(subtaskData);
                return;
            }
        }

        // 判断下一级是否子流程节点，且是否存在候选人
        NextOrPrevFo fo = new NextOrPrevFo();
        fo.setDeploymentId(deploymentId);
        fo.setTaskKey(subCode);
        List<FlowableNodeModel> nextModels = flowAbleUrl.getNext(fo);

        for (FlowableNodeModel nextModel : nextModels) {
            TemplateNodeEntity nodeEntity = parentNodeList.stream()
                    .filter(e -> ObjectUtil.equals(e.getNodeCode(), nextModel.getId()))
                    .findFirst().orElse(new TemplateNodeEntity());
            if (ObjectUtil.equals(nodeEntity.getNodeType(), NodeEnum.subFlow.getType())) {
                NodeModel subFlow = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
                TemplateEntity template = templateService.getById(subFlow.getFlowId());
                TemplateJsonEntity subJsonEntity = templateJsonService.getById(template.getFlowId());
                List<TemplateNodeEntity> subNodeList = templateNodeService.getList(template.getFlowId());
                Map<String, NodeModel> subNodes = new HashMap<>();
                for (TemplateNodeEntity node : subNodeList) {
                    subNodes.put(node.getNodeCode(), JsonUtil.getJsonToBean(node.getNodeJson(), NodeModel.class));
                }
                TemplateNodeEntity subStart = subNodeList.stream()
                        .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst()
                        .orElse(new TemplateNodeEntity());

                FlowMethod method = new FlowMethod();
                method.setDeploymentId(subJsonEntity.getFlowableId());
                method.setNodes(subNodes);
                method.setNodeEntityList(subNodeList);
                method.setNodeCode(subStart.getNodeCode());

                if (this.checkBranch(subStart)) {
                    throw new WorkFlowException(MsgCode.WF121.get());
                }
                List<NodeModel> nextApprover = this.getNextApprover(method);
                if (!this.checkNextCandidates(nextApprover)) {
                    throw new WorkFlowException(MsgCode.WF121.get());
                }
                FlowModel model = new FlowModel();
                model.setDeploymentId(flowModel.getDeploymentId());
                model.setNodeEntityList(subNodeList);
                if (this.checkNextError(model, nextApprover, false, false) != 0) {
                    throw new WorkFlowException(MsgCode.WF121.get());
                }
            }
        }

        if (nodeModel.getIsAsync().equals(FlowNature.ChildAsync)) {
            // 异步已经完成节点
            return;
        }
        // 父节点下的子流程
        QueryWrapper<TaskEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TaskEntity::getParentId, taskEntity.getParentId())
                .eq(TaskEntity::getSubCode, subCode);
        List<TaskEntity> subList = taskService.list(wrapper);
        // 未审批集合
        List<TaskEntity> unfinishedList = subList.stream()
                .filter(e -> !e.getStatus().equals(TaskStatusEnum.PASSED.getCode())
                        && !e.getStatus().equals(TaskStatusEnum.REJECTED.getCode()))
                .collect(Collectors.toList());
        if (unfinishedList.isEmpty()) {
            FlowModel model = JsonUtil.getJsonToBean(flowModel, FlowModel.class);
            model.setFinishFlag(true);
            subList = subList.stream().filter(e -> null != e.getEndTime())
                    .sorted(Comparator.comparing(TaskEntity::getEndTime).reversed()).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(subList)) {
                TaskEntity finalTask = subList.get(0);
                model.setHandleStatus(
                        ObjectUtil.equals(finalTask.getStatus(), TaskStatusEnum.PASSED.getCode()) ? 1 : 0);
            } else {
                model.setHandleStatus(1);
            }
            String formId = parentNode.getFormId();
            this.setFlowModel(parentTask.getId(), model);
            Map<String, NodeModel> nodes = model.getNodes();
            Map<String, Object> formData = serviceUtil.infoData(formId, parentTask.getId());
            model.setFormData(formData);
            FlowMethod flowMethod = new FlowMethod();
            flowMethod.setDeploymentId(model.getDeploymentId());
            flowMethod.setNodeCode(subCode);
            flowMethod.setFormData(formData);
            flowMethod.setNodes(nodes);
            flowMethod.setTaskEntity(parentTask);
            Map<String, Boolean> resMap = conditionService.handleCondition(flowMethod);
            flowMethod.setFlowModel(model);
            flowMethod.setFlowableTaskId(flowableTaskId);
            flowMethod.setResMap(resMap);
            flowMethod.setNodeEntityList(parentNodeList);
            // 递归subCode的所有上级节点，获取审批节点的经办
            model.setOperatorEntity(new OperatorEntity());
            List<String> nodeCodeList = new ArrayList<>();
            prevNodeList(flowModel.getDeploymentId(), subCode, parentNodeList, nodeCodeList);
            if (CollectionUtil.isNotEmpty(nodeCodeList)) {
                List<OperatorEntity> list = operatorUtil.getList(parentTask.getId(), nodeCodeList);
                if (CollectionUtil.isNotEmpty(list)) {
                    model.setOperatorEntity(list.get(0));
                }
            }
            operatorUtil.completeNode(flowMethod);
        }
    }

    // 删除子流程（退回时若是重新审批）
    public void deleteSubflow(String taskId, List<String> nodeCodeList) {
        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskEntity::getParentId, taskId);
        if (CollectionUtil.isNotEmpty(nodeCodeList)) {
            queryWrapper.lambda().in(TaskEntity::getSubCode, nodeCodeList);
        }
        List<TaskEntity> list = taskService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            List<String> idList = list.stream().map(TaskEntity::getId).distinct().collect(Collectors.toList());
            List<String> idAll = new ArrayList<>();
            taskService.deleTaskAll(idList, idAll);
            taskService.setIgnoreLogicDelete().removeByIds(idAll);
            taskService.clearIgnoreLogicDelete();
        }
    }

    /**
     * 判断任务是否在挂起状态
     *
     * @param taskEntity 任务
     */
    public void isSuspend(TaskEntity taskEntity) throws WorkFlowException {
        Integer status = taskEntity != null ? taskEntity.getStatus() : null;
        if (TaskStatusEnum.PAUSED.getCode().equals(status)) {
            throw new WorkFlowException(MsgCode.WF114.get());
        }
    }

    /**
     * 判断任务是否终止状态
     *
     * @param taskEntity 任务
     */
    public void isCancel(TaskEntity taskEntity) throws WorkFlowException {
        Integer status = taskEntity != null ? taskEntity.getStatus() : null;
        if (ObjectUtil.equals(TaskStatusEnum.CANCEL.getCode(), status)) {
            throw new WorkFlowException(MsgCode.WF123.get());
        }
    }

    /**
     * 获取审批人
     *
     * @param flowMethod
     * @return
     */
    public List<String> userListAll(FlowMethod flowMethod) throws WorkFlowException {
        List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();
        TemplateNodeEntity nodeEntity = flowMethod.getNodeEntity();
        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);

        TemplateNodeEntity globalEntity = nodeEntityList.stream()
                .filter(t -> NodeEnum.global.getType().equals(t.getNodeType())).findFirst().get();
        NodeModel global = JsonUtil.getJsonToBean(globalEntity.getNodeJson(), NodeModel.class);
        Integer errRule = global.getErrorRule();
        List<String> errRuleUser = global.getErrorRuleUser();
        // 子流程去获取指定成员、异常处理
        if (StringUtil.equals(nodeModel.getType(), NodeEnum.subFlow.getType())) {
            errRule = nodeModel.getErrorRule();
            errRuleUser = nodeModel.getErrorRuleUser();
        }

        Boolean errorRule = flowMethod.getErrorRule();
        int pass = 0;
        int notSubmit = 0;
        int node = 0;
        Boolean extraRule = flowMethod.getExtraRule();
        TaskEntity taskEntity = flowMethod.getTaskEntity();

        List<String> userIdAll = user(flowMethod, nodeModel.getAssigneeType());
        // String admin = serviceUtil.getAdmin();
        // userIdAll = userIdAll.stream().filter(e -> !ObjectUtil.equals(e,
        // admin)).distinct().collect(Collectors.toList());
        // 附加规则
        if (extraRule && !ObjectUtil.equals(nodeModel.getAssigneeType(), FlowTaskOperatorEnum.Candidate.getCode())) {
            rule(userIdAll, taskEntity.getId(), nodeModel.getExtraRule());
        }
        // 获取最新用户
        List<UserEntity> userList = serviceUtil.getUserName(userIdAll, true);

        // 子流程权限
        if (StringUtil.equals(nodeModel.getType(), NodeEnum.subFlow.getType())) {
            String flowId = nodeModel.getFlowId();
            TemplateEntity template = templateService.getById(flowId);
            if (template != null && template.getVisibleType().equals(2) && ObjectUtil.equals(template.getStatus(), 1)) {
                List<UserEntity> list = new ArrayList<>(userList);
                for (UserEntity user : list) {
                    if (serviceUtil.isCommonUser(user.getId())) {
                        List<String> flowIds = serviceUtil.getLaunchPermission(user.getId());
                        // 权限中不存在 该流程版本
                        if (!flowIds.contains(flowId)) {
                            UserEntity userEntity = list.stream().filter(e -> e.getId().equals(user.getId()))
                                    .findFirst().orElse(null);
                            if (null != userEntity) {
                                userList.remove(user);
                            }
                        }
                    }
                }
            }
        }
        userIdAll = userList.stream().map(UserEntity::getId).collect(Collectors.toList());

        // 异常规则
        if (errorRule && userList.size() == 0) {
            // 异常处理规则
            switch (ErrorRuleEnum.getByCode(errRule)) {
                case administrator:
                    userIdAll.add(serviceUtil.getAdmin());
                    break;
                case initiator:
                    List<UserEntity> errorRuleUser = serviceUtil.getUserName(errRuleUser, true);
                    if (errorRuleUser.size() > 0) {
                        userIdAll.addAll(errorRuleUser.stream().map(UserEntity::getId).collect(Collectors.toList()));
                    } else {
                        userIdAll.add(serviceUtil.getAdmin());
                    }
                    break;
                case node:
                    String nodeId = nodeEntity.getNodeCode();
                    List<CandidatesEntity> list = candidatesService.getList(taskEntity.getId(), nodeId);
                    for (CandidatesEntity t : list) {
                        List<String> candidates = StringUtil.isNotEmpty(t.getCandidates())
                                ? Arrays.stream(t.getCandidates().split(",")).collect(Collectors.toList())
                                : new ArrayList<>();
                        userIdAll.addAll(candidates);
                    }
                    node++;
                    break;
                case pass:
                    pass++;
                    break;
                case notSubmit:
                    notSubmit++;
                    break;
                case creatorUserId:
                    userIdAll.add(taskEntity.getCreatorUserId());
                    break;
                default:
                    break;
            }
        }
        flowMethod.setPass(pass);
        flowMethod.setNotSubmit(notSubmit);
        flowMethod.setNode(node);
        return userIdAll;
    }

    /**
     * 附加条件
     */
    public void rule(List<String> userIdAll, String taskId, int rule) {
        List<Integer> ruleList = ImmutableList.of(ExtraRuleEnum.organize.getCode(), ExtraRuleEnum.position.getCode(),
                ExtraRuleEnum.manager.getCode(), ExtraRuleEnum.subordinate.getCode(),
                ExtraRuleEnum.department.getCode());
        if (ruleList.contains(rule)) {
            LaunchUserEntity flowUser = launchUserService.getInfoByTask(taskId);
            if (flowUser != null) {
                List<UserEntity> userList = serviceUtil.getUserName(userIdAll, true);
                List<String> userListAll = userList.stream().map(UserEntity::getId).collect(Collectors.toList());
                Map<String, List<UserRelationEntity>> relationUserList = serviceUtil.getListByUserIdAll(userListAll)
                        .stream().filter(t -> StringUtil.isNotEmpty(t.getObjectId()))
                        .collect(Collectors.groupingBy(UserRelationEntity::getObjectId));
                // 附加条件
                switch (ExtraRuleEnum.getByCode(rule)) {
                    case organize:
                        List<String> organize = new ArrayList<>();
                        OrganizeEntity organizeInfo = serviceUtil.getOrganizeInfo(flowUser.getOrganizeId());
                        if (null != organizeInfo
                                && Objects.equals(organizeInfo.getCategory(), PermissionConst.DEPARTMENT)) {
                            organize.addAll(relationUserList.get(flowUser.getOrganizeId()) != null
                                    ? relationUserList.get(flowUser.getOrganizeId()).stream()
                                            .map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                    : new ArrayList<>());
                        }
                        userIdAll.retainAll(organize);
                        break;
                    case position:
                        List<String> position = new ArrayList<>();
                        position.addAll(relationUserList.get(flowUser.getPositionId()) != null
                                ? relationUserList.get(flowUser.getPositionId()).stream()
                                        .map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                : new ArrayList<>());
                        userIdAll.retainAll(position);
                        break;
                    case manager:
                        List<String> manager = new ArrayList<>();
                        manager.add(flowUser.getSuperior());
                        userIdAll.retainAll(manager);
                        break;
                    case subordinate:
                        List<String> subordinate = new ArrayList<>();
                        subordinate.addAll(StringUtil.isNotEmpty(flowUser.getSubordinate())
                                ? new ArrayList<>(Arrays.asList(flowUser.getSubordinate().split(",")))
                                : new ArrayList<>());
                        userIdAll.retainAll(subordinate);
                        break;
                    case department:
                        List<String> department = new ArrayList<>();
                        List<String> departmentAll = serviceUtil.getDepartmentAll(flowUser.getOrganizeId()).stream()
                                .map(OrganizeEntity::getId).collect(Collectors.toList());
                        for (String id : departmentAll) {
                            department.addAll(relationUserList.get(id) != null ? relationUserList.get(id).stream()
                                    .map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                    : new ArrayList<>());
                        }
                        userIdAll.retainAll(department);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    // 附加条件过滤
    public void rule(List<String> userIdAll, UserEntity flowUser, int rule) {
        List<Integer> ruleList = ImmutableList.of(ExtraRuleEnum.organize.getCode(), ExtraRuleEnum.position.getCode(),
                ExtraRuleEnum.manager.getCode(), ExtraRuleEnum.subordinate.getCode(),
                ExtraRuleEnum.department.getCode());
        if (ruleList.contains(rule)) {
            if (flowUser != null) {
                List<UserEntity> userList = serviceUtil.getUserName(userIdAll, true);
                List<String> userListAll = userList.stream().map(UserEntity::getId).collect(Collectors.toList());
                Map<String, List<UserRelationEntity>> relationUserList = serviceUtil.getListByUserIdAll(userListAll)
                        .stream().filter(t -> StringUtil.isNotEmpty(t.getObjectId()))
                        .collect(Collectors.groupingBy(UserRelationEntity::getObjectId));
                // 附加条件
                switch (ExtraRuleEnum.getByCode(rule)) {
                    case organize:
                        List<String> organize = new ArrayList<>();
                        OrganizeEntity organizeInfo = serviceUtil.getOrganizeInfo(flowUser.getOrganizeId());
                        if (null != organizeInfo
                                && Objects.equals(organizeInfo.getCategory(), PermissionConst.DEPARTMENT)) {
                            organize.addAll(relationUserList.get(flowUser.getOrganizeId()) != null
                                    ? relationUserList.get(flowUser.getOrganizeId()).stream()
                                            .map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                    : new ArrayList<>());
                        }
                        userIdAll.retainAll(organize);
                        break;
                    case position:
                        List<String> position = new ArrayList<>();
                        String positionId = flowUser.getPositionId();
                        position.addAll(relationUserList.get(positionId) != null ? relationUserList.get(positionId)
                                .stream().map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                : new ArrayList<>());
                        userIdAll.retainAll(position);
                        break;
                    case manager:
                        List<String> manager = new ArrayList<>();
                        String managerId = flowUser.getManagerId();
                        manager.add(managerId);
                        userIdAll.retainAll(manager);
                        break;
                    case department:
                        List<String> department = new ArrayList<>();
                        List<String> departmentAll = serviceUtil.getDepartmentAll(flowUser.getOrganizeId()).stream()
                                .map(OrganizeEntity::getId).collect(Collectors.toList());
                        for (String id : departmentAll) {
                            department.addAll(relationUserList.get(id) != null ? relationUserList.get(id).stream()
                                    .map(UserRelationEntity::getUserId).collect(Collectors.toList())
                                    : new ArrayList<>());
                        }
                        userIdAll.retainAll(department);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    public void getByRule(List<String> userIdAll, UserEntity flowUser, int rule) {
        if (flowUser != null) {
            String userId = flowUser.getId();
            String orgId = flowUser.getOrganizeId();
            List<String> objectIds = new ArrayList<>();
            // 附加条件
            switch (ExtraRuleEnum.getByCode(rule)) {
                case organize:
                    OrganizeEntity organizeInfo = serviceUtil.getOrganizeInfo(orgId);
                    if (null != organizeInfo
                            && ObjectUtil.equals(organizeInfo.getCategory(), PermissionConst.DEPARTMENT)) {
                        objectIds.add(orgId);
                        List<UserRelationEntity> orgRelationList = serviceUtil.getListByObjectIdAll(objectIds);
                        List<String> org = orgRelationList.stream().map(UserRelationEntity::getUserId)
                                .filter(id -> !ObjectUtil.equals(id, userId)).collect(Collectors.toList());
                        userIdAll.addAll(org);
                    }
                    break;
                case position:
                    String positionId = flowUser.getPositionId();
                    objectIds.add(positionId);
                    List<UserRelationEntity> positionRelationList = serviceUtil.getListByObjectIdAll(objectIds);
                    List<String> position = positionRelationList.stream().map(UserRelationEntity::getUserId)
                            .filter(id -> !ObjectUtil.equals(id, userId)).collect(Collectors.toList());
                    userIdAll.addAll(position);
                    break;
                case role:
                    List<RoleEntity> curRolesByOrgId = serviceUtil.getCurRolesByOrgId(orgId);
                    List<String> roleIds = curRolesByOrgId.stream().map(RoleEntity::getId).collect(Collectors.toList());
                    List<UserRelationEntity> listByObjectIdAll = serviceUtil.getListByObjectIdAll(roleIds);

                    List<String> userIds = listByObjectIdAll.stream().map(UserRelationEntity::getUserId)
                            .filter(id -> !ObjectUtil.equals(id, userId)).collect(Collectors.toList());
                    userIdAll.addAll(userIds);
                    break;
                case group:
                    List<String> ids = new ArrayList<>();
                    ids.add(userId);
                    List<UserRelationEntity> listByUserIdAll = serviceUtil.getListByUserIdAll(ids);
                    List<String> groupIds = listByUserIdAll.stream()
                            .filter(e -> ObjectUtil.equals(e.getObjectType(), PermissionConst.GROUP))
                            .map(UserRelationEntity::getObjectId).collect(Collectors.toList());
                    List<UserRelationEntity> relations = serviceUtil.getListByObjectIdAll(groupIds);
                    List<String> collect = relations.stream().map(UserRelationEntity::getUserId)
                            .filter(id -> !ObjectUtil.equals(id, userId)).collect(Collectors.toList());
                    userIdAll.addAll(collect);
                    break;
            }
        }
    }

    /**
     * 封装查询审批人
     */
    private List<String> user(FlowMethod flowMethod, int type) throws WorkFlowException {
        List<String> userIdAll = new ArrayList<>();
        TemplateNodeEntity nodeEntity = flowMethod.getNodeEntity();
        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        String createUserId = taskEntity.getCreatorUserId();
        FlowModel flowModel = flowMethod.getFlowModel();
        OperatorEntity operator = flowModel.getOperatorEntity();
        String deploymentId = flowModel.getDeploymentId();
        List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();
        List<String> prevList = new ArrayList<>();
        TemplateNodeEntity startNode = nodeEntityList.stream()
                .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.start.getType())).findFirst().orElse(null);
        boolean prevIsStart = false;
        // 发起者【部门主管】
        if (FlowTaskOperatorEnum.DepartmentCharge.getCode().equals(type)) {
            this.prevNode(deploymentId, nodeEntity.getNodeCode(), nodeEntityList, prevList);
            if (null != startNode) {
                prevIsStart = prevList.contains(startNode.getNodeCode());
            }
            // 判断 发起人、上一节点
            Integer managerType = nodeModel.getManagerApproverType();
            if (ObjectUtil.equals(managerType, 2) && !prevIsStart) {
                List<String> handleIds = this.getHandleIds(taskEntity.getId(), operator);
                List<UserEntity> userList = serviceUtil.getUserName(handleIds);

                for (UserEntity user : userList) {
                    OrganizeEntity organizeEntity = getManageOrgByLevel(user.getOrganizeId(), 1);
                    if (null != organizeEntity) {
                        userIdAll.add(organizeEntity.getManagerId());
                    }
                }
            } else {
                LaunchUserEntity launchUser = launchUserService.getInfoByTask(taskEntity.getId());
                String orgId;
                if (launchUser != null) {
                    orgId = launchUser.getOrganizeId();
                } else {
                    UserEntity info = serviceUtil.getUserInfo(createUserId);
                    orgId = info == null ? "" : info.getOrganizeId();
                }
                OrganizeEntity organizeEntity = getManageOrgByLevel(orgId, 1);
                if (organizeEntity != null) {
                    userIdAll.add(organizeEntity.getManagerId());
                }
            }
        }
        // 发起者【发起者主管】
        if (FlowTaskOperatorEnum.LaunchCharge.getCode().equals(type)) {
            this.prevNode(deploymentId, nodeEntity.getNodeCode(), nodeEntityList, prevList);
            if (null != startNode) {
                prevIsStart = prevList.contains(startNode.getNodeCode());
            }
            // 判断 发起人、上一节点
            Integer approverType = nodeModel.getApproverType();
            if (ObjectUtil.equals(approverType, 2) && !prevIsStart) {
                List<String> handleIds = this.getHandleIds(taskEntity.getId(), operator);
                List<UserEntity> userList = serviceUtil.getUserName(handleIds);

                for (UserEntity user : userList) {
                    String managerByLevel = getManagerByLevel(user.getManagerId(), nodeModel.getManagerLevel());
                    if (StringUtil.isNotEmpty(managerByLevel)) {
                        userIdAll.add(managerByLevel);
                    }
                }
            } else {
                UserEntity info = serviceUtil.getUserInfo(createUserId);
                if (info != null) {
                    String managerByLevel = getManagerByLevel(info.getManagerId(), nodeModel.getManagerLevel());
                    if (StringUtil.isNotEmpty(managerByLevel)) {
                        userIdAll.add(managerByLevel);
                    }
                }
            }
        }
        // 【发起本人】
        if (FlowTaskOperatorEnum.InitiatorMe.getCode().equals(type)) {
            userIdAll.add(createUserId);
        }
        // 【变量】
        if (FlowTaskOperatorEnum.Variate.getCode().equals(type)) {
            flowMethod.setIsAssign(false);
            flowMethod.setIsData(true);
            Map<String, Object> dataAll = flowMethod.getSubFormData();
            if (CollectionUtil.isEmpty(dataAll)) {
                dataAll = createOrUpdate(flowMethod);
            }
            Object data = this.getOneData(dataAll, nodeModel.getFormField());
            if (ObjectUtil.isNotEmpty(data)) {
                List<String> list = new ArrayList<>();
                try {
                    List<List<String>> dataList = JsonUtil.getJsonToBean(data, List.class);
                    for (List<String> ids : dataList) {
                        for (String id : ids) {
                            list.add(id);
                        }
                    }
                } catch (Exception e) {
                    try {
                        List<String> dataList = JsonUtil.getJsonToList(data, String.class);
                        for (String id : dataList) {
                            list.add(id);
                        }
                    } catch (Exception e1) {
                        list.addAll(Arrays.asList(String.valueOf(data).split(",")));
                    }
                }
                List<String> id = new ArrayList<>();
                for (String s : list) {
                    id.add(s.split("--")[0]);
                }
                List<UserRelationEntity> listByObjectIdAll = serviceUtil.getListByObjectIdAll(id);
                List<String> userPosition = listByObjectIdAll.stream().map(UserRelationEntity::getUserId)
                        .collect(Collectors.toList());
                List<String> handleIdAll = new ArrayList<>();
                handleIdAll.addAll(userPosition);
                handleIdAll.addAll(id);
                userIdAll.addAll(handleIdAll);
            }
        }
        // 【环节】
        if (FlowTaskOperatorEnum.Tache.getCode().equals(type)) {
            List<RecordEntity> list = recordUtil.getList(taskEntity.getId());
            list = list.stream().filter(e -> ObjectUtil.equals(e.getNodeCode(), nodeModel.getApproverNodeId())
                    && (FlowNature.AuditCompletion.equals(e.getHandleType())
                            || FlowNature.RejectCompletion.equals(e.getHandleType()))
                    && !FlowNature.Invalid.equals(e.getStatus()) && !e.getHandleId().equals(FlowNature.SYSTEM_CODE)
                    && !e.getHandleId().equals("0"))
                    .collect(Collectors.toList());
            List<String> handleId = list.stream().map(RecordEntity::getHandleId).collect(Collectors.toList());
            userIdAll.addAll(handleId);
        }
        // 【服务】
        if (FlowTaskOperatorEnum.Serve.getCode().equals(type)) {
            flowMethod.setIsAssign(false);
            flowMethod.setIsData(true);
            Map<String, Object> dataAll = createOrUpdate(flowMethod);
            InterfaceConfig interfaceConfig = nodeModel.getInterfaceConfig();
            String interfaceId = interfaceConfig.getInterfaceId();
            if (StringUtil.isNotEmpty(interfaceId)) {
                UserInfo userInfo = UserProvider.getUser();
                List<TemplateJsonModel> templateJsonModelList = interfaceConfig.getTemplateJson();
                RecordEntity record = new RecordEntity();
                record.setTaskId(taskEntity.getId());
                record.setNodeCode(nodeEntity.getNodeCode());
                record.setHandleId(userInfo.getUserId());
                // UserEntity createUser =
                // serviceUtil.getUserInfo(taskEntity.getCreatorUserId());
                // UserEntity delegate = StringUtil.isNotEmpty(taskEntity.getDelegateUserId()) ?
                // serviceUtil.getUserInfo(taskEntity.getDelegateUserId()) : null;
                Map<String, String> parameterMap = msgUtil.parameterMap(dataAll, templateJsonModelList, record,
                        taskEntity);
                ActionResult result = serviceUtil.infoToId(interfaceId, parameterMap);
                if (Objects.equals(200, result.getCode())) {
                    Object data = result.getData();
                    if (data instanceof Map) {
                        JSONObject map = new JSONObject((Map) data);
                        List<String> handleId = StringUtil.isNotEmpty(map.getString("handleId"))
                                ? Arrays.asList(map.getString("handleId").split(","))
                                : new ArrayList<>();
                        userIdAll.addAll(handleId);
                    }
                }
            }
        }
        // 【候选人】
        if (FlowTaskOperatorEnum.Candidate.getCode().equals(type)) {
            String nodeCode = nodeEntity.getNodeCode();
            List<CandidatesEntity> candidatesList = candidatesService.getList(taskEntity.getId(), nodeCode);
            if (CollectionUtil.isNotEmpty(candidatesList)) {
                List<String> opIds = candidatesList.stream().map(CandidatesEntity::getOperatorId)
                        .collect(Collectors.toList());
                List<OperatorEntity> operators = operatorService.listByIds(opIds);
                for (CandidatesEntity t : candidatesList) {
                    OperatorEntity op = operators.stream().filter(e -> ObjectUtil.equals(e.getId(), t.getOperatorId()))
                            .findFirst().orElse(null);
                    if (null != op && null == op.getHandleStatus() && null != op.getHandleParameter()) {
                        continue;
                    }
                    List<String> candidates = StringUtil.isNotEmpty(t.getCandidates())
                            ? Arrays.stream(t.getCandidates().split(",")).collect(Collectors.toList())
                            : new ArrayList<>();
                    userIdAll.addAll(candidates);
                }
            }
        }
        // 【指定人】
        if (FlowTaskOperatorEnum.Nominator.getCode().equals(type)) {
            List<String> list = this.getSub(nodeModel);
            List<String> handleIdAll = serviceUtil.getUserListAll(list);
            userIdAll.addAll(handleIdAll);
        }
        return userIdAll;
    }

    public Object getOneData(Map<String, Object> map, String key) {
        Object obj = null;
        if (null != map) {
            obj = map.get(key + FlowNature.FORM_FIELD_SUFFIX);
            if (null == obj) {
                obj = map.get(key);
            }
        }
        return obj;
    }

    public List<String> getSub(NodeModel nodeModel) {
        return this.getSub(nodeModel.getApprovers());
    }

    public List<String> getSub(List<String> approvers) {
        List<String> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(approvers)) {
            list.addAll(approvers);
            List<String> consts = ImmutableList.of(PermissionConst.COMPANY, PermissionConst.DEPARTMENT);
            // 获取公司、部门的所有下级
            for (String approver : approvers) {
                String[] split = approver.split("--");
                if (split.length > 1 && consts.contains(split[1])) {
                    List<String> childOrg = serviceUtil.getChildOrg(split[0]);
                    list.addAll(childOrg);
                }
            }
            list = list.stream().distinct().collect(Collectors.toList());
        }
        return list;
    }

    // 根据经办获取上一审批节点的审批人
    public List<String> getHandleIds(String taskId, OperatorEntity operator) {
        List<String> handleIds = new ArrayList<>();
        List<OperatorEntity> operatorList = operatorUtil.getList(taskId);
        if (CollectionUtil.isNotEmpty(operatorList)) {
            List<OperatorEntity> list = operatorList.stream()
                    .filter(e -> e.getHandleTime() != null && ObjectUtil.equals(e.getNodeId(), operator.getNodeId()))
                    .collect(Collectors.toList());
            handleIds = list.stream().map(OperatorEntity::getHandleId).distinct().collect(Collectors.toList());
        }
        if (CollectionUtil.isEmpty(handleIds)) {
            handleIds.add(operator.getHandleId());
        }
        return handleIds;
    }

    /**
     * 递归上级部门
     *
     * @param
     * @return
     * @copyright 深圳市乐程软件有限公司
     * @date 2024/6/29
     */
    private OrganizeEntity getManageOrgByLevel(String organizeId, long level) {
        --level;
        if (level == 0) {
            return serviceUtil.getOrganizeInfo(organizeId);
        } else {
            OrganizeEntity organizeInfo = serviceUtil.getOrganizeInfo(organizeId);
            return organizeInfo != null ? getManageOrgByLevel(organizeInfo.getParentId(), level) : null;
        }
    }

    /**
     * 递归主管
     *
     * @param managerId 主管id
     * @param level     第几级
     * @return
     */
    public String getManagerByLevel(String managerId, long level) {
        --level;
        if (level == 0) {
            return managerId;
        } else {
            UserEntity userEntity = serviceUtil.getUserInfo(managerId);
            return userEntity != null ? getManagerByLevel(userEntity.getManagerId(), level) : "";
        }
    }

    /**
     * 保存、更新数据，仅处理数据
     */
    public Map<String, Object> createOrUpdate(FlowMethod flowMethod) throws WorkFlowException {
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        TemplateNodeEntity nodeEntity = flowMethod.getNodeEntity();
        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);

        List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();

        FlowModel flowModel = flowMethod.getFlowModel();
        boolean voluntarily = flowModel.getVoluntarily();
        boolean isData = flowMethod.getIsData();
        Map<String, Object> formData = flowModel.getFormData();
        Map<String, Object> data = new HashMap<>();
        // 保存数据的表单
        String formId = nodeEntity.getFormId();
        // 子流程选择的流程版本id
        String flowId = nodeEntity.getFlowId();
        String taskId = taskEntity.getId();

        List<Integer> handleStatus = ImmutableList.of(FlowRecordEnum.audit.getCode(), FlowRecordEnum.submit.getCode());
        // 递归
        List<String> nodeIdList = new ArrayList<>();
        prevNodeList(flowModel.getDeploymentId(), nodeEntity.getNodeCode(), nodeEntityList, nodeIdList);
        List<RecordEntity> list = recordService.getRecordList(taskId, handleStatus).stream()
                .filter(t -> nodeIdList.contains(t.getNodeCode()))
                .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed())
                .collect(Collectors.toList());
        List<String> recordNodeIdList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (i == 0) {
                recordNodeIdList.add(list.get(i).getNodeCode());
            }
        }
        List<TemplateNodeEntity> taskNodeEntity = nodeEntityList.stream()
                .filter(t -> nodeIdList.contains(t.getNodeCode())).collect(Collectors.toList());
        if (taskNodeEntity.size() == 0) {
            taskNodeEntity.addAll(nodeEntityList.stream().filter(t -> recordNodeIdList.contains(t.getNodeCode()))
                    .collect(Collectors.toList()));
        }
        String taskNodeFormId = "";
        String nodeCode = "";
        if (CollectionUtil.isNotEmpty(list)) {
            nodeCode = list.get(0).getNodeCode();
        } else {
            if (!taskNodeEntity.isEmpty()) {
                nodeCode = taskNodeEntity.get(0).getNodeCode();
            }
        }
        if (!taskNodeEntity.isEmpty()) {
            formData.put(FlowConstant.PREV_NODE_FORM_ID, taskNodeEntity.get(0).getFormId());
        }
        if (StringUtil.isNotEmpty(taskNodeFormId) && isData) {
            Map<String, Object> taskNodeData = infoData(taskNodeFormId, taskId);
            if (NodeEnum.subFlow.getType().equals(nodeModel.getType()) || voluntarily) {
                if (NodeEnum.subFlow.getType().equals(nodeModel.getType())) {
                    taskNodeData.put(FlowFormConstant.FLOWID, flowId);
                }
                formData.putAll(taskNodeData);
            }
        }
        String resultNodeCode = nodeCode;
        List<Assign> assignList = nodeModel.getAssignList().stream().filter(e -> e.getNodeId().equals(resultNodeCode))
                .collect(Collectors.toList());
        // 获取当前表单
        Map<String, Object> thisNodeData = infoData(formId, taskId);
        data.putAll(thisNodeData);
        data.putAll(formData(formData, assignList, taskEntity, flowMethod));
        return data;
    }

    /**
     * 处理数据传递，并存储在线程，后续保存数据库
     */
    public Map<String, Object> dataTransfer(FlowMethod flowMethod) throws WorkFlowException {
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        TemplateNodeEntity nodeEntity = flowMethod.getNodeEntity();
        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
        FlowModel flowModel = flowMethod.getFlowModel();
        Map<String, Object> formData = flowModel.getFormData();

        List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();

        TemplateNodeEntity globalEntity = nodeEntityList.stream()
                .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.global.getType())).findFirst().orElse(null);
        // 判断是否能数据传递
        if (null != globalEntity) {
            NodeModel global = JsonUtil.getJsonToBean(globalEntity.getNodeJson(), NodeModel.class);
            if (!global.getHasAloneConfigureForms()) {
                return formData;
            }
        }
        if (CollectionUtil.isEmpty(nodeModel.getAssignList())) {
            return formData;
        }

        boolean voluntarily = flowModel.getVoluntarily();
        boolean isAssign = flowMethod.getIsAssign();
        boolean isData = flowMethod.getIsData();

        Map<String, Object> data = new HashMap<>();
        // 保存数据的表单
        String formId = nodeEntity.getFormId();
        // 子流程选择的流程版本id
        String flowId = nodeEntity.getFlowId();
        String taskId = taskEntity.getId();

        List<Integer> handleStatus = ImmutableList.of(FlowRecordEnum.audit.getCode(), FlowRecordEnum.submit.getCode());
        // 递归
        List<String> nodeIdList = new ArrayList<>();
        prevNodeList(flowModel.getDeploymentId(), nodeEntity.getNodeCode(), nodeEntityList, nodeIdList);
        List<RecordEntity> list = recordService.getRecordList(taskId, handleStatus).stream()
                .filter(t -> nodeIdList.contains(t.getNodeCode()))
                .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed())
                .collect(Collectors.toList());
        List<String> recordNodeIdList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (i == 0) {
                recordNodeIdList.add(list.get(i).getNodeCode());
            }
        }
        List<TemplateNodeEntity> taskNodeEntity = nodeEntityList.stream()
                .filter(t -> nodeIdList.contains(t.getNodeCode())).collect(Collectors.toList());
        if (taskNodeEntity.size() == 0) {
            taskNodeEntity.addAll(nodeEntityList.stream().filter(t -> recordNodeIdList.contains(t.getNodeCode()))
                    .collect(Collectors.toList()));
        }
        String taskNodeFormId = "";
        String nodeCode = "";
        if (CollectionUtil.isNotEmpty(list)) {
            nodeCode = list.get(0).getNodeCode();
        } else {
            if (!taskNodeEntity.isEmpty()) {
                nodeCode = taskNodeEntity.get(0).getNodeCode();
            }
        }
        if (!taskNodeEntity.isEmpty()) {
            formData.put(FlowConstant.PREV_NODE_FORM_ID, taskNodeEntity.get(0).getFormId());
        }
        if (StringUtil.isNotEmpty(taskNodeFormId) && isData) {
            Map<String, Object> taskNodeData = infoData(taskNodeFormId, taskId);
            if (NodeEnum.subFlow.getType().equals(nodeModel.getType()) || voluntarily) {
                if (NodeEnum.subFlow.getType().equals(nodeModel.getType())) {
                    taskNodeData.put(FlowFormConstant.FLOWID, flowId);
                }
                formData.putAll(taskNodeData);
            }
        }
        String resultNodeCode = nodeCode;
        List<Assign> assignList = nodeModel.getAssignList().stream().filter(e -> e.getNodeId().equals(resultNodeCode))
                .collect(Collectors.toList());
        // 获取当前表单
        Map<String, Object> thisNodeData = infoData(formId, taskId);
        data.putAll(thisNodeData);
        data.putAll(formData(formData, assignList, taskEntity, flowMethod));
        List<String> typeList = ImmutableList.of(NodeEnum.end.getType(), NodeEnum.subFlow.getType());
        if (isAssign) {
            boolean isWrite = !typeList.contains(nodeModel.getType());
            FlowContextHolder.addChildData(taskId, formId, data, new ArrayList<>(), isWrite);
        }
        return data;
    }

    /**
     * 获取上级节点
     *
     * @param deploymentId   部署id
     * @param nodeCode       节点编码
     * @param nodeEntityList 节点集合
     * @param nodeCodeList   上一级节点编码集合
     */
    public void prevNodeList(String deploymentId, String nodeCode, List<TemplateNodeEntity> nodeEntityList,
            List<String> nodeCodeList) throws WorkFlowException {
        NextOrPrevFo fo = new NextOrPrevFo();
        fo.setDeploymentId(deploymentId);
        fo.setTaskKey(nodeCode);
        List<String> prevList = flowAbleUrl.getPrev(fo);
        if (CollectionUtil.isNotEmpty(prevList)) {
            for (String prev : prevList) {
                TemplateNodeEntity nodeEntity = nodeEntityList.stream().filter(e -> e.getNodeCode().equals(prev))
                        .findFirst().orElse(null);
                if (nodeEntity != null) {
                    // 获取 不是子流程类型的节点
                    if (nodeEntity.getNodeType().equals(NodeEnum.subFlow.getType())) {
                        prevNodeList(deploymentId, nodeEntity.getNodeCode(), nodeEntityList, nodeCodeList);
                    } else {
                        nodeCodeList.add(nodeEntity.getNodeCode());
                    }
                }
            }
        }
    }

    /**
     * 获取上级节点，不过滤子流程节点
     *
     * @param deploymentId   部署id
     * @param nodeCode       节点编码
     * @param nodeEntityList 节点集合
     * @param nodeCodeList   上一级节点编码集合
     */
    public void prevNode(String deploymentId, String nodeCode, List<TemplateNodeEntity> nodeEntityList,
            List<String> nodeCodeList) throws WorkFlowException {
        NextOrPrevFo fo = new NextOrPrevFo();
        fo.setDeploymentId(deploymentId);
        fo.setTaskKey(nodeCode);
        List<String> prevList = flowAbleUrl.getPrev(fo);
        if (CollectionUtil.isNotEmpty(prevList)) {
            for (String prev : prevList) {
                TemplateNodeEntity nodeEntity = nodeEntityList.stream().filter(e -> e.getNodeCode().equals(prev))
                        .findFirst().orElse(null);
                if (nodeEntity != null) {
                    nodeCodeList.add(nodeEntity.getNodeCode());
                }
            }
        }
    }

    /**
     * 查询表单值
     *
     * @return
     */
    public Map<String, Object> infoData(String formId, String taskId) throws WorkFlowException {
        Map<String, Map<String, Object>> allData = FlowContextHolder.getAllData();
        Map<String, Object> dataAll = allData.get(taskId + "_yunzhupaas_" + formId) != null
                ? allData.get(taskId + "_yunzhupaas_" + formId)
                : serviceUtil.infoData(formId, taskId);
        return dataAll;
    }

    // 截取数据传递字段，获取表单id
    public List<AssignRule> handleAssignRule(List<AssignRule> ruleList) {
        List<AssignRule> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ruleList)) {
            for (AssignRule assignRule : ruleList) {
                AssignRule rule = JsonUtil.getJsonToBean(assignRule, AssignRule.class);
                String parentField = assignRule.getParentField();
                int index = parentField.lastIndexOf("|");
                if (index != -1) {
                    String field = parentField.substring(0, index);
                    rule.setParentField(field);
                    String substring = parentField.substring(index + 1);
                    rule.setFormId(substring);
                }
                list.add(rule);
            }
        }
        return list;
    }

    // 表单赋值
    public Map<String, Object> formData(Map<String, Object> formData, List<Assign> assignListAll, TaskEntity taskEntity,
            FlowMethod flowMethod) throws WorkFlowException {
        String taskId = taskEntity.getId();
        List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();
        TemplateNodeEntity startNode = nodeEntityList.stream()
                .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.start.getType())).findFirst().orElse(null);
        if (startNode != null) {
            formData.put(FlowNature.StartNodeFormId, startNode.getFormId());
        }

        Map<String, Object> result = new HashMap<>(formData);
        Map<String, Object> oldData = new HashMap<>(formData);

        Map<String, Map<String, Object>> map = new HashMap<>();

        // 全局参数
        String globalParameter = taskEntity.getGlobalParameter();
        Map<String, Object> taskMap = globalParameter != null ? JsonUtil.stringToMap(globalParameter) : new HashMap<>();

        for (Assign assignModel : assignListAll) {
            List<AssignRule> ruleList = this.handleAssignRule(assignModel.getRuleList());
            for (AssignRule assignMode : ruleList) {
                String parentField = assignMode.getParentField();
                String[] parentFieldList = parentField.split("-");
                String childField = assignMode.getChildField();
                String[] childFieldList = childField.split("-");

                if (childFieldList.length > 1 && parentFieldList.length > 1) {
                    int end = 0;
                    if (oldData.get(parentFieldList[0]) instanceof List) {
                        List<Map<String, Object>> parentList = (List<Map<String, Object>>) oldData
                                .get(parentFieldList[0]);
                        end = parentList.size();
                    }
                    if (result.get(childFieldList[0]) instanceof List) {
                        List<Map<String, Object>> childList = (List<Map<String, Object>>) result.get(childFieldList[0]);
                        for (int i = 0; i < childList.size() - end; i++) {
                            childList.add(new HashMap<>());
                        }
                    } else {
                        List<Map<String, Object>> childList = new ArrayList<>();
                        for (int i = 0; i < end; i++) {
                            childList.add(new HashMap<>());
                        }
                        result.put(childFieldList[0], childList);
                        result.put(childFieldList[0] + FlowNature.FORM_FIELD_SUFFIX, childList);
                    }
                }
            }
        }

        for (Assign assignModel : assignListAll) {
            List<AssignRule> ruleList = this.handleAssignRule(assignModel.getRuleList());
            for (AssignRule assignMode : ruleList) {
                String formId = assignMode.getFormId();
                if (StringUtil.equals(formId, FlowNature.GLOBAL_PARAMETER)) {
                    oldData.putAll(taskMap);
                } else {
                    Map<String, Object> mapData = map.get(formId);
                    if (CollectionUtil.isEmpty(mapData)) {
                        Map<String, Object> data = serviceUtil.infoData(formId, taskId);
                        map.put(formId, data);
                        oldData.putAll(data);
                    }
                }
                // 子表处理规则
                String parentField = assignMode.getParentField();
                String[] parentFieldList = parentField.split("-");
                String childField = assignMode.getChildField();
                String[] childFieldList = childField.split("-");
                Object childData = getSysParamData(oldData, parentField, taskId);
                if (childFieldList.length > 1) {
                    List<Map<String, Object>> childMapAll = new ArrayList<>();
                    if (result.get(childFieldList[0]) instanceof List) {
                        List<Map<String, Object>> childList = (List<Map<String, Object>>) result.get(childFieldList[0]);
                        for (Map<String, Object> objectMap : childList) {
                            Map<String, Object> childMap = new HashMap<>(objectMap);
                            childMapAll.add(childMap);
                        }
                    }
                    if (parentFieldList.length > 1) {
                        if (oldData.get(parentFieldList[0]) instanceof List) {
                            List<Map<String, Object>> parentList = (List<Map<String, Object>>) oldData
                                    .get(parentFieldList[0]);
                            int num = parentList.size() - childMapAll.size();
                            for (int i = 0; i < num; i++) {
                                childMapAll.add(new HashMap<>());
                            }
                            for (int i = 0; i < parentList.size(); i++) {
                                Map<String, Object> parentMap = parentList.get(i);
                                Map<String, Object> childMap = childMapAll.get(i);
                                childMap.put(childFieldList[1], parentMap.get(parentFieldList[1]));
                            }
                        }
                    } else {
                        // 主传子
                        if (1 > childMapAll.size()) {
                            childMapAll.add(new HashMap<>());
                        }
                        for (Map<String, Object> childMap : childMapAll) {
                            childMap.put(childFieldList[1], childData);
                        }
                    }
                    result.put(childFieldList[0], childMapAll);
                    result.put(childFieldList[0] + FlowNature.FORM_FIELD_SUFFIX, childMapAll);
                } else {
                    if (parentFieldList.length > 1) {
                        if (oldData.get(parentFieldList[0]) instanceof List) {
                            List<Map<String, Object>> parentList = (List<Map<String, Object>>) oldData
                                    .get(parentFieldList[0]);
                            for (int i = 0; i < parentList.size(); i++) {
                                Map<String, Object> parentMap = parentList.get(i);
                                if (i == 0) {
                                    childData = parentMap.get(parentFieldList[1]);
                                }
                            }
                        }
                    }
                    result.put(childField, childData);
                    result.put(childField + FlowNature.FORM_FIELD_SUFFIX, childData);
                }
            }
        }
        return result;
    }

    /**
     * 处理系统参数：
     *
     * @prevNodeFormId上节点表单id
     */
    private Object getSysParamData(Map<String, Object> formData, String parentField, String taskId) {
        Object data;
        if (FlowConstant.PREV_NODE_FORM_ID.equals(parentField)) {
            data = taskId;
        } else {
            data = formData.get(parentField);
        }
        return data;
    }

    // true为选择分支
    public boolean checkBranch(TemplateNodeEntity nodeEntity) {
        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
        return this.checkBranch(nodeModel);
    }

    public boolean checkBranch(NodeModel nodeModel) {
        String divideRule = nodeModel.getDivideRule();
        return ObjectUtil.equals(DivideRuleEnum.CHOOSE.getType(), divideRule);
    }

    // false为候选人
    public boolean checkNextCandidates(List<NodeModel> nodeList) {
        if (CollectionUtil.isNotEmpty(nodeList)) {
            for (NodeModel node : nodeList) {
                if (node.getAssigneeType().equals(FlowTaskOperatorEnum.Candidate.getCode())) {
                    return false;
                }
            }
        }
        return true;
    }

    public int checkNextError(FlowModel flowModel, List<NodeModel> nextApprover, boolean nodeFlag,
            boolean notSubmitFlag) throws WorkFlowException {
        return this.checkNextError(flowModel, nextApprover, nodeFlag, notSubmitFlag, false);
    }

    // 判断异常处理是否是 上一节点审批人指定处理人、无法提交
    public int checkNextError(FlowModel flowModel, List<NodeModel> nextApprover, boolean nodeFlag,
            boolean notSubmitFlag, boolean errorFlag) throws WorkFlowException {
        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
        TaskEntity taskEntity = flowModel.getTaskEntity();
        List<FlowErrorModel> errorList = new ArrayList<>();
        for (NodeModel nodeModel : nextApprover) {
            // 候选人节点跳过
            if (ObjectUtil.equals(nodeModel.getAssigneeType(), FlowTaskOperatorEnum.Candidate.getCode())) {
                continue;
            }
            TemplateNodeEntity nodeEntity = nodeEntityList.stream()
                    .filter(e -> e.getNodeCode().equals(nodeModel.getNodeId())).findFirst().orElse(null);
            // 获取审批人
            FlowMethod flowMethod = new FlowMethod();
            flowMethod.setFlowModel(flowModel);
            flowMethod.setTaskEntity(taskEntity);
            flowMethod.setNodeEntity(nodeEntity);
            flowMethod.setNodeEntityList(nodeEntityList);
            flowMethod.setErrorRule(true);
            flowMethod.setExtraRule(true);
            List<String> userIds = this.userListAll(flowMethod);

            Integer node = flowMethod.getNode();
            Integer notSubmit = flowMethod.getNotSubmit();

            if (node > 0) {
                if (nodeFlag) {
                    operatorUtil.handleErrorRule(nodeModel, errorList);
                } else {
                    return 1;
                }
            }
            if (notSubmit > 0) {
                if (notSubmitFlag) {
                    throw new WorkFlowException(MsgCode.WF061.get());
                }
                return 2;
            }
        }
        if (errorFlag && CollectionUtil.isNotEmpty(errorList)) {
            flowModel.setErrorList(errorList);
            return 3;
        }
        if (!errorList.isEmpty()) {
            AuditModel model = new AuditModel();
            model.setErrorCodeList(errorList);
            throw new WorkFlowException(200, JsonUtil.getObjectToString(model));
        }
        return 0;
    }

    /**
     * 获取下一级审批节点
     */
    public List<NodeModel> getNextApprover(FlowMethod flowMethod) throws WorkFlowException {
        String deploymentId = flowMethod.getDeploymentId();
        String nodeCode = flowMethod.getNodeCode();
        Map<String, NodeModel> nodes = flowMethod.getNodes();
        List<NodeModel> nextNode = flowMethod.getNextNode();

        // 获取下一级节点
        NextOrPrevFo fo = new NextOrPrevFo();
        fo.setDeploymentId(deploymentId);
        fo.setTaskKey(nodeCode);
        List<FlowableNodeModel> nextList = flowAbleUrl.getNext(fo);

        if (CollectionUtil.isNotEmpty(nextList)) {
            OutgoingFlowsFo flowsFo = new OutgoingFlowsFo();
            flowsFo.setDeploymentId(deploymentId);
            flowsFo.setTaskKey(nodeCode);
            List<String> outgoingFlows = flowAbleUrl.getOutgoingFlows(flowsFo);
            Map<String, Boolean> res = new HashMap<>();

            flowMethod.setOutgoingFlows(outgoingFlows);
            flowMethod.setResMap(res);
            conditionService.getConditionResult(flowMethod);
            conditionService.checkCondition(res, nodes);

            for (FlowableNodeModel next : nextList) {
                // 判断条件，子流程的出线 条件都为false 则跳过
                Map<String, Boolean> resMap = new HashMap<>();
                flowMethod.setOutgoingFlows(next.getIncomingList());
                flowMethod.setResMap(resMap);
                flowMethod.setNodeCode(next.getId());
                conditionService.getConditionResult(flowMethod);
                try {
                    conditionService.checkCondition(resMap, nodes);
                } catch (WorkFlowException e) {
                    continue;
                }
                NodeModel nodeModel = nodes.get(next.getId());
                if (null != nodeModel) {
                    // 子流程往下递归
                    if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) {
                        if (flowMethod.getNextSubFlow()) {
                            nextNode.add(nodeModel);
                        }
                        getNextApprover(flowMethod);
                    } else {
                        nextNode.add(nodeModel);
                    }
                }
            }
        }
        return nextNode;
    }

    // 删除表单数据
    public void deleteFormData(List<TaskEntity> taskList) throws Exception {
        if (taskList.isEmpty()) {
            return;
        }
        List<TemplateNodeEntity> nodeEntityList = new ArrayList<>();
        List<String> flowIds = taskList.stream().map(TaskEntity::getFlowId).collect(Collectors.toList());
        if (!flowIds.isEmpty()) {
            nodeEntityList = templateNodeService.getList(flowIds, null);
        }

        for (TaskEntity taskEntity : taskList) {
            List<String> formIds = nodeEntityList.stream()
                    .filter(e -> e.getFlowId().equals(taskEntity.getFlowId()) && StringUtil.isNotBlank(e.getFormId()))
                    .map(TemplateNodeEntity::getFormId).distinct().collect(Collectors.toList());
            for (String formId : formIds) {
                serviceUtil.deleteFormData(formId, taskEntity.getId());
            }
        }
    }

    public List<String> getNextList(String deploymentId, String nodeCode, Map<String, NodeModel> nodes,
            List<String> nextList) throws WorkFlowException {
        nextList = nextList != null ? nextList : new ArrayList<>();
        NextOrPrevFo fo = new NextOrPrevFo();
        fo.setDeploymentId(deploymentId);
        fo.setTaskKey(nodeCode);
        List<FlowableNodeModel> nextModels = flowAbleUrl.getNext(fo);
        for (FlowableNodeModel next : nextModels) {

            NodeModel nodeModel = nodes.get(next.getId());
            if (null != nodeModel) {
                // 子流程往下递归
                if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) {
                    nextList.add(next.getId());
                    getNextList(deploymentId, next.getId(), nodes, nextList);
                } else {
                    nextList.add(next.getId());
                }
            }
        }
        return nextList;
    }

    public List<TaskEntity> getSubTask(String taskId, List<String> nodeCodes) {
        if (StringUtil.isEmpty(taskId)) {
            return new ArrayList<>();
        }
        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskEntity::getParentId, taskId);
        if (CollectionUtil.isNotEmpty(nodeCodes)) {
            queryWrapper.lambda().in(TaskEntity::getSubCode, nodeCodes);
        }
        return taskService.list(queryWrapper);
    }

    public void checkTemplateHide(String templateId) throws WorkFlowException {
        TemplateEntity template = templateService.getById(templateId);
        if (null != template) {
            List<Integer> templateStatus = ImmutableList.of(1, 2);
            if (!templateStatus.contains(template.getStatus())) {
                throw new WorkFlowException(MsgCode.WF140.get());
            }
        }
    }

    public ActionResult launchFlow(FlowModel flowModel) throws Exception {
        String templateId = flowModel.getTemplateId();
        List<String> userIds = flowModel.getUserIds();
        List<Map<String, Object>> formDataList = flowModel.getFormDataList();
        if (CollectionUtil.isEmpty(formDataList)) {
            return ActionResult.fail("未选择记录，发起失败");
        }
        TemplateEntity template = templateService.getById(templateId);
        if (null == template) {
            return ActionResult.fail(MsgCode.WF122.get());
        }
        if (!ObjectUtil.equals(template.getStatus(), 1)) {
            throw new WorkFlowException(MsgCode.WF140.get());
        }
        TemplateJsonEntity jsonEntity = templateJsonService.getById(template.getFlowId());
        List<TemplateNodeEntity> nodeEntityList = templateNodeService.getList(jsonEntity.getId());
        Map<String, NodeModel> nodes = new HashMap<>();
        for (TemplateNodeEntity node : nodeEntityList) {
            nodes.put(node.getNodeCode(), JsonUtil.getJsonToBean(node.getNodeJson(), NodeModel.class));
        }
        FlowMethod method = new FlowMethod();
        method.setDeploymentId(jsonEntity.getFlowableId());
        TemplateNodeEntity startNode = nodeEntityList.stream()
                .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst()
                .orElse(new TemplateNodeEntity());
        if (this.checkBranch(startNode)) {
            throw new WorkFlowException(MsgCode.WF147.get());
        }
        method.setNodeCode(startNode.getNodeCode());
        method.setNodes(nodes);
        method.setNodeEntityList(nodeEntityList);
        Map<String, Boolean> resMap = conditionService.handleCondition(method);
        // 判断条件、候选人
        try {
            conditionService.checkCondition(resMap, nodes);
        } catch (WorkFlowException e) {
            throw new WorkFlowException(MsgCode.WF133.get());
        }
        method.setNextSubFlow(true);
        List<NodeModel> nextApprover = this.getNextApprover(method);
        if (!this.checkNextCandidates(nextApprover)) {
            throw new WorkFlowException(MsgCode.WF134.get());
        }

        String flowId = jsonEntity.getId();
        // 判断流程权限
        List<String> userListAll = serviceUtil.getUserListAll(userIds);
        FlowFormModel formIdAndFlowId = templateService.getFormIdAndFlowId(userListAll, templateId);
        List<UserEntity> userList = serviceUtil.getUserName(formIdAndFlowId.getUserId(), true);
        if (CollectionUtil.isEmpty(userList)) {
            throw new WorkFlowException(MsgCode.WF136.get());
        }
        for (UserEntity user : userList) {
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(user.getId());
            userInfo.setUserName(user.getRealName());

            FlowModel model = new FlowModel();
            model.setUserInfo(userInfo);
            model.setFlowId(flowId);
            model.setStatus(1);
            model.setDeploymentId(jsonEntity.getFlowableId());
            model.setNodeEntityList(nodeEntityList);
            for (Map<String, Object> formData : formDataList) {
                model.setFormData(formData);
                if (this.checkNextError(model, nextApprover, false, false) != 0) {
                    throw new WorkFlowException(MsgCode.WF135.get());
                }
                taskService.batchSaveOrSubmit(model);
                TaskEntity taskEntity = model.getTaskEntity();
                if (taskEntity.getRejectDataId() == null) {
                    operatorUtil.autoAudit(model);
                    operatorUtil.handleEvent();
                }
            }
        }
        return ActionResult.success(MsgCode.SU006.get());
    }
}
