package cn.stylefeng.workflow.instance.core.actions.gateway;


import cn.stylefeng.workflow.api.entity.design.Node;
import cn.stylefeng.workflow.api.entity.instance.RuntimeNode;
import cn.stylefeng.workflow.api.enums.NodeStatusEnum;
import cn.stylefeng.workflow.api.enums.NodeTypeEnum;
import cn.stylefeng.workflow.api.pojo.InstanceContext;
import cn.stylefeng.workflow.instance.api.node.NodeAction;
import cn.stylefeng.workflow.instance.api.pojo.NodeActionResult;
import cn.stylefeng.workflow.instance.core.path.NodePathCalc;
import cn.stylefeng.workflow.instance.modular.manage.service.RuntimeNodeService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class ParallelNodeAction extends NodeAction {

    @Resource
    private RuntimeNodeService runtimeNodeService;

    @Override
    public NodeTypeEnum getNodeType() {
        return NodeTypeEnum.PARALLEL_JOIN;
    }

    @Override
    public NodeActionResult doAction(Node nodeInfo, InstanceContext instanceContext) {

        RuntimeNode currentRuntimeNode = null;

        currentRuntimeNode = runtimeNodeService.getInstanceRuntimeNodeByNodeId(instanceContext.getRuntimeInstance().getInstanceId(), nodeInfo.getNodeId());
        if (currentRuntimeNode == null) {
            currentRuntimeNode = super.createRuntimeNode(nodeInfo, instanceContext);
        }

        List<Long> currentBeforeNodeIdList = new NodePathCalc(instanceContext).getNodeBeforeNodeIdList(nodeInfo.getNodeId());

        boolean haveAlreadyFinishLastRuntimeNode = true;
        for (Long beforeNodeId : currentBeforeNodeIdList) {
            RuntimeNode lastRuntimeNode = runtimeNodeService.getInstanceRuntimeNodeByNodeId(
                    instanceContext.getRuntimeInstance().getInstanceId(), beforeNodeId);


            if (lastRuntimeNode == null || !NodeStatusEnum.FINISH.getStatus().equals(lastRuntimeNode.getNodeStatus())) {
                haveAlreadyFinishLastRuntimeNode = false;
            }

        }

        if (haveAlreadyFinishLastRuntimeNode) {
            currentRuntimeNode.setNodeStatus(NodeStatusEnum.FINISH.getStatus());
            super.saveOrUpdateRuntimeNode(currentRuntimeNode);

            List<Node> nextNodeList = this.calcNextNodeList(nodeInfo, instanceContext);
            return new NodeActionResult(currentRuntimeNode, nextNodeList, instanceContext.getInstanceVariable());
        }

        else {
            currentRuntimeNode.setNodeStatus(NodeStatusEnum.RUNNING.getStatus());
            super.saveOrUpdateRuntimeNode(currentRuntimeNode);
            return new NodeActionResult(currentRuntimeNode, null, instanceContext.getInstanceVariable());
        }

    }

}
