package cn.stylefeng.workflow.instance.core.actions.approver.base;


import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.workflow.api.entity.design.Node;
import cn.stylefeng.workflow.api.entity.instance.RuntimeNode;
import cn.stylefeng.workflow.api.enums.ApproverNodeTypeEnum;
import cn.stylefeng.workflow.api.enums.NodeStatusEnum;
import cn.stylefeng.workflow.api.pojo.InstanceContext;
import cn.stylefeng.workflow.api.pojo.InstanceVariable;
import cn.stylefeng.workflow.api.pojo.config.node.NodeData;
import cn.stylefeng.workflow.api.pojo.config.node.approver.ApproverConfig;
import cn.stylefeng.workflow.api.pojo.config.node.approver.ApproverStrategy;
import cn.stylefeng.workflow.api.pojo.config.node.approver.detail.NodeApproverPerson;
import cn.stylefeng.workflow.instance.api.InstanceVariableApi;
import cn.stylefeng.workflow.instance.api.node.NodeAction;
import cn.stylefeng.workflow.instance.api.pojo.NodeActionResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public abstract class BaseApprovalNodeAction extends NodeAction {

    @Resource
    private InstanceVariableApi instanceVariableApi;

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

        RuntimeNode thisRuntimeNode = super.createRuntimeNode(nodeInfo, instanceContext);
        thisRuntimeNode.setNodeStatus(NodeStatusEnum.RUNNING.getStatus());
        thisRuntimeNode = super.saveRuntimeNode(thisRuntimeNode);

        this.fillPointUserIdList(nodeInfo, instanceContext);

        this.createWaitToDoTask(nodeInfo, thisRuntimeNode, instanceContext);

        return new NodeActionResult(thisRuntimeNode, null, instanceContext.getInstanceVariable());
    }

    protected abstract void createWaitToDoTask(Node node, RuntimeNode runtimeNode, InstanceContext instanceContext);

    private void fillPointUserIdList(Node nodeInfo, InstanceContext instanceContext) {

        NodeData nodeData = nodeInfo.getNodeData();
        if (ObjectUtil.isEmpty(nodeData)) {
            return;
        }

        ApproverConfig approverConfig = nodeData.getApproverConfig();
        if (approverConfig == null) {
            return;
        }

        ApproverStrategy approverStrategy = approverConfig.getApproverStrategy();
        if (approverStrategy == null) {
            return;
        }

        if (!ApproverNodeTypeEnum.ONE_BY_ONE.getMode().equals(approverStrategy.getApproverNodeType())) {
            return;
        }

        List<Long> nodeConfigApproverUserIdList = approverConfig.getMainApprover().getNodeApproverPersonList().stream().map(NodeApproverPerson::getUserId).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(nodeConfigApproverUserIdList)) {
            return;
        }

        InstanceVariable instanceVariable = instanceContext.getInstanceVariable();
        Map<Long, List<Long>> pointNodeApproverUserId = instanceVariable.getPointNodeApproverUserId();
        if (ObjectUtil.isEmpty(pointNodeApproverUserId)) {
            pointNodeApproverUserId = new HashMap<>();
            instanceVariable.setPointNodeApproverUserId(pointNodeApproverUserId);
        }

        List<Long> userIdList = pointNodeApproverUserId.get(nodeInfo.getNodeId());
        if (ObjectUtil.isEmpty(userIdList)) {

            pointNodeApproverUserId.put(nodeInfo.getNodeId(), nodeConfigApproverUserIdList);

            instanceVariableApi.updateInstanceVariable(instanceContext.getRuntimeInstance().getInstanceId(), instanceVariable);
        }

    }

}
