package com.yunzhupaas.flowable.util;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.ImmutableList;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.TaskEntity;
import com.yunzhupaas.flowable.enums.DivideRuleEnum;
import com.yunzhupaas.flowable.enums.NodeEnum;
import com.yunzhupaas.flowable.model.flowable.FlowAbleUrl;
import com.yunzhupaas.flowable.model.flowable.OutgoingFlowsFo;
import com.yunzhupaas.flowable.model.task.FlowMethod;
import com.yunzhupaas.flowable.model.templatenode.nodejson.NodeModel;
import com.yunzhupaas.flowable.model.templatenode.nodejson.ProperCond;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/19 15:14
 */
@Component
public class ConditionService {
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private FlowAbleUrl flowAbleUrl;

    // 处理选择分支的条件
    public Map<String, Boolean> getForBranch(FlowMethod flowMethod, List<String> branchList) throws WorkFlowException {
        Map<String, Boolean> resMap = new HashMap<>();

        String deploymentId = flowMethod.getDeploymentId();
        String nodeCode = flowMethod.getNodeCode();
        Map<String, NodeModel> nodes = flowMethod.getNodes();
        NodeModel global = nodes.get(NodeEnum.global.getType());
        List<String> connectList = global.getConnectList();
        List<String> typeList = ImmutableList.of(NodeEnum.trigger.getType());

        OutgoingFlowsFo flowsFo = new OutgoingFlowsFo();
        flowsFo.setDeploymentId(deploymentId);
        flowsFo.setTaskKey(nodeCode);
        List<String> outgoingFlows = flowAbleUrl.getOutgoingFlows(flowsFo);

        for (String flow : outgoingFlows) {
            resMap.put(flow, false);
            if (!connectList.contains(flow)) {
                // 不存在connectList中，说明是隐藏的线，默认给true
                resMap.put(flow, true);
                continue;
            }
            List<String> nodeKey = flowAbleUrl.getTaskKeyAfterFlow(deploymentId, flow);
            if (CollectionUtil.isNotEmpty(nodeKey)) {
                NodeModel nodeModel = nodes.get(nodeKey.get(0));
                if (null != nodeModel && typeList.contains(nodeModel.getType())) {
                    resMap.put(flow, true);
                } else if (branchList.contains(nodeKey.get(0))) {
                    resMap.put(flow, true);
                }
            }
        }

        return resMap;
    }

    /**
     * 处理条件
     */
    public Map<String, Boolean> handleCondition(FlowMethod flowMethod) throws WorkFlowException {
        String deploymentId = flowMethod.getDeploymentId();
        String nodeCode = flowMethod.getNodeCode();
        // 获取节点的出线
        OutgoingFlowsFo flowsFo = new OutgoingFlowsFo();
        flowsFo.setDeploymentId(deploymentId);
        flowsFo.setTaskKey(nodeCode);
        List<String> outgoingFlows = flowAbleUrl.getOutgoingFlows(flowsFo);

        Map<String, Boolean> resMap = new HashMap<>();
        flowMethod.setResMap(resMap);
        flowMethod.setOutgoingFlows(outgoingFlows);
        // 判断条件
        getConditionResult(flowMethod);
        return resMap;
    }

    /**
     * 获取条件结果
     */
    public void getConditionResult(FlowMethod flowMethod) {
        List<String> outgoingFlows = flowMethod.getOutgoingFlows();
        Map<String, Boolean> resMap = flowMethod.getResMap();
        Map<String, NodeModel> nodes = flowMethod.getNodes();
        String nodeCode = flowMethod.getNodeCode();
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        if (CollectionUtil.isNotEmpty(outgoingFlows)) {

            Set<String> userList = new HashSet<>();
            userList.add(UserProvider.getLoginUserId());

            if (taskEntity != null) {
                userList.add(taskEntity.getCreatorUserId());
                if (StringUtil.isNotEmpty(taskEntity.getDelegateUserId())) {
                    userList.add(taskEntity.getDelegateUserId());
                }
            }

            List<UserEntity> userName = serviceUtil.getUserName(new ArrayList<>(userList));
            UserEntity createUser = null;
            UserEntity delegate = null;
            if (taskEntity != null) {
                createUser = userName.stream().filter(e -> Objects.equals(e.getId(), taskEntity.getCreatorUserId()))
                        .findFirst().orElse(null);
                if (StringUtil.isNotEmpty(taskEntity.getDelegateUserId())) {
                    delegate = userName.stream().filter(e -> Objects.equals(e.getId(), taskEntity.getDelegateUserId()))
                            .findFirst().orElse(null);
                }
            }

            // 设置条件判断 所需参数
            UserEntity userEntity = userName.stream()
                    .filter(e -> Objects.equals(e.getId(), UserProvider.getLoginUserId())).findFirst().orElse(null);
            flowMethod.setUserEntity(userEntity);
            if (flowMethod.getUserInfo() == null) {
                flowMethod.setUserInfo(UserProvider.getUser());
            }
            flowMethod.setCreateUser(createUser);
            flowMethod.setDelegate(delegate);

            NodeModel currentNodeModel = nodes.get(nodeCode);
            flowMethod.setNodeModel(currentNodeModel);
            if (StringUtil.equals(currentNodeModel.getDivideRule(), DivideRuleEnum.PARALLEL.getType())) {
                // 并行，全都为true
                for (String key : outgoingFlows) {
                    resMap.put(key, true);
                }
            }
            // else if (StringUtil.equals(currentNodeModel.getDivideRule(),
            // DivideRuleEnum.EXCLUSIVE.getType())) {
            // // 排他，获取到第一条为true的结果，其余默认为false
            // for (String key : outgoingFlows) {
            // // 获取出线节点 判断条件，没有设置条件的默认true
            // NodeModel nodeModel = nodes.get(key);
            // boolean res = true;
            // if (null != nodeModel) {
            // List<ProperCond> conditions = nodeModel.getConditions();
            // if (CollectionUtil.isNotEmpty(conditions)) {
            // flowMethod.setConditions(conditions);
            // flowMethod.setMatchLogic(nodeModel.getMatchLogic());
            // res = FlowJsonUtil.nodeConditionDecide(flowMethod);
            // }
            // conditionResMap.put(key, res);
            // }
            // resMap.put(key, res);
            // }
            // }
            else {
                for (String key : outgoingFlows) {
                    // 获取出线节点 判断条件，没有设置条件的默认true
                    NodeModel nodeModel = nodes.get(key);
                    boolean res = true;
                    if (null != nodeModel) {
                        List<ProperCond> conditions = nodeModel.getConditions();
                        if (CollectionUtil.isNotEmpty(conditions)) {
                            flowMethod.setConditions(conditions);
                            flowMethod.setMatchLogic(nodeModel.getMatchLogic());
                            res = FlowJsonUtil.nodeConditionDecide(flowMethod);
                        }
                    }
                    resMap.put(key, res);
                }
            }
        }
    }

    // 处理条件
    public boolean hasCondition(FlowMethod flowMethod) {
        TaskEntity taskEntity = flowMethod.getTaskEntity();
        UserEntity createUser = null;
        UserEntity delegate = null;
        if (taskEntity != null) {
            createUser = serviceUtil.getUserInfo(taskEntity.getCreatorUserId());
            delegate = StringUtil.isNotEmpty(taskEntity.getDelegateUserId())
                    ? serviceUtil.getUserInfo(taskEntity.getDelegateUserId())
                    : null;
        }
        flowMethod.setCreateUser(createUser);
        flowMethod.setDelegate(delegate);
        UserEntity userEntity = serviceUtil.getUserInfo(UserProvider.getLoginUserId());
        flowMethod.setUserEntity(userEntity);
        flowMethod.setUserInfo(UserProvider.getUser());
        return FlowJsonUtil.nodeConditionDecide(flowMethod);
    }

    public void checkCondition(Map<String, Boolean> resMap, Map<String, NodeModel> nodes) throws WorkFlowException {
        if (CollectionUtil.isEmpty(nodes)) {
            return;
        }
        NodeModel global = nodes.get(NodeEnum.global.getType());
        if (null == global) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        List<String> connectList = global.getConnectList();
        long count = resMap.values().stream().filter(t -> Objects.equals(t, true)).count();
        Set<String> set = resMap.keySet();

        if (count == resMap.size()) {
            return;
        }

        if (CollectionUtil.isNotEmpty(connectList)) {
            int c = 0;
            for (String key : set) {
                if (connectList.contains(key) && resMap.get(key)) {
                    c++;
                }
            }
            if (c < 1) {
                throw new WorkFlowException(MsgCode.WF075.get());
            }
        } else {
            if (count < 1) {
                throw new WorkFlowException(MsgCode.WF075.get());
            }
        }
    }
}
