package cn.fateverse.workflow.process.cmd;

import cn.fateverse.workflow.entity.bo.AnalysisProcessBo;
import cn.fateverse.workflow.entity.dto.TaskDto;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.delegate.ActivityBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.Task;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 驳回用户审批执行器
 *
 * @author Clay
 * @date 2023-03-21
 */
public class RollbackUserTaskCmd implements Command<String>, Serializable {

    private final RuntimeService runtimeService;
    private final Task task;
    private final TaskDto taskDto;
    private final AnalysisProcessBo processBo;
    private final Process process;

    public RollbackUserTaskCmd(RuntimeService runtimeService,
                               Task task, TaskDto taskDto,
                               AnalysisProcessBo processBo, Process process) {
        this.runtimeService = runtimeService;
        this.task = task;
        this.taskDto = taskDto;
        this.processBo = processBo;
        this.process = process;
    }


    @Override
    public String execute(CommandContext commandContext) {
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(task.getProcessInstanceId()).list();
        //过滤出需要删除的执行器
        List<String> executionIds = executions.stream()
                .filter(execution -> processBo.getLeaveMergeNodeSet().contains(execution.getActivityId()) || processBo.getRollbackNodeSet().contains(execution.getActivityId()))
                .map(Execution::getId).collect(Collectors.toList());

        //通过执行器就行驳回
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(task.getProcessInstanceId())
                .moveExecutionsToSingleActivityId(executionIds, taskDto.getRollBackId())
                .changeState();
        // 需要解析当前节点和目标节点的相对位置
        //1. 当前节点和目标节点都不在网关内 (无需处理)
        //2. 当前节点在网关内,目标节点在上一级网关外,或理解为目标节点相对当前节点在并行网关外 (无需处理)
        //3. 当前节点不在网关内,目标节点在网关内 (需要处理)
        //4. 当前节点和目标节点在不同的网关类 (需要处理)
        if (!processBo.getEnterMergeNodeSet().isEmpty()) {
            ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
            String parentId = executions.iterator().next().getParentId();
            ExecutionEntity parentExecutionEntity = executionEntityManager.findById(parentId);
            for (String targetInSpecialGatewayEndId : processBo.getEnterMergeNodeSet()) {
                FlowNode targetInSpecialGatewayEnd = (FlowNode) process.getFlowElement(targetInSpecialGatewayEndId);
                int nbrOfExecutionsToJoin = targetInSpecialGatewayEnd.getIncomingFlows().size();
                // 处理目标节点所处的分支以外的分支,即 总分枝数-1 = nbrOfExecutionsToJoin - 1
                for (int i = 0; i < nbrOfExecutionsToJoin - 1; i++) {
                    ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity);
                    childExecution.setCurrentFlowElement(targetInSpecialGatewayEnd);
                    ActivityBehavior activityBehavior = (ActivityBehavior) targetInSpecialGatewayEnd.getBehavior();
                    activityBehavior.execute(childExecution);
                }
            }
        }
        return null;
    }
}
