package com.cmvr.test.flow.runtime.engine.support;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.test.enums.BranchConditionOpEnum;
import com.cmvr.test.flow.builder.FlowBranchConditionGroup;
import com.cmvr.test.flow.context.TaskContext;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 分支节点条件匹配器
 * 用于在流程执行时，根据输入参数判断分支条件是否命中
 */
public class FlowBranchEvaluator {

    /**
     * 选择满足条件的锚点ID
     * 遍历所有条件组，返回第一个满足条件的分支ID
     * 如果都不满足，返回默认的 else 出口
     */
    public static String evaluate(TaskContext taskContext, List<Integer> iterations, String nodeId, List<FlowBranchConditionGroup> groups, JSONObject inputParams) {
        // 先合并上游输出参数
        mergeParams(taskContext,iterations, inputParams, groups);
        for (FlowBranchConditionGroup group : groups) {
            if (matchGroup(group, inputParams)) {
                return group.getId();
            }
        }
        return nodeId + "_else";
    }

    /**
     * 获取分支节点引用节点的输出参数，并合并到当前计算参数列表中
     */
    private static void mergeParams(TaskContext taskContext, List<Integer> iterations, JSONObject inputParams, List<FlowBranchConditionGroup> groups) {
        if (CollUtil.isEmpty(taskContext.getNodeOutputs())) {
            return;
        }
        HashSet<String> quoteIds = new HashSet<>();
        for (FlowBranchConditionGroup group : groups) {
            List<FlowBranchConditionGroup.ConditionExpression> expressions = group.getExpressions();
            for (FlowBranchConditionGroup.ConditionExpression expression : expressions) {
                if (expression.getNameType().equalsIgnoreCase("quote")) {
                    List<String> nameQuotePath = expression.getNameQuotePath();
                    if (CollUtil.isNotEmpty(nameQuotePath) && nameQuotePath.get(0).length() == 32) {
                        quoteIds.add(nameQuotePath.get(0));
                    }
                }
            }
        }
        for (String quoteId : quoteIds) {
            JSONObject nodeOutput = taskContext.getNodeOutput(quoteId, iterations);
            if (ObjUtil.isNotEmpty(nodeOutput)) {
                // 合并进inputParams
                inputParams.putAll(nodeOutput);
            }
        }
    }

    /**
     * 匹配某个条件组是否成立
     */
    private static boolean matchGroup(FlowBranchConditionGroup group, JSONObject context) {
        boolean isAnd = "and".equalsIgnoreCase(group.getWithOr());

        for (FlowBranchConditionGroup.ConditionExpression expr : group.getExpressions()) {
            boolean result = matchExpr(expr, context);

            if (!isAnd && result) {
                return true;
            }
            if (isAnd && !result) {
                return false;
            }
        }

        return isAnd;
    }

    /**
     * 匹配单个表达式是否成立
     */
    private static boolean matchExpr(FlowBranchConditionGroup.ConditionExpression expr, JSONObject context) {
        // 取左值：
        Object left;
        if ("quote".equalsIgnoreCase(expr.getNameType()) && expr.getNameQuotePath() != null) {
            // 如果时引用类型，取其引用字段的值
            left = resolveQuotePath(context, expr.getNameQuotePath());
        } else {
            // 如果是输入类型，取其输入的值
            left = expr.getName();
        }

        // 取右值：可以是常量值，也可以是引用路径值
        String right;
        if ("quote".equalsIgnoreCase(expr.getValueType()) && expr.getQuotePath() != null) {
            right = resolveQuotePath(context, expr.getQuotePath());
        } else {
            right = expr.getInput();
        }

        // 获取比较运算符
        BranchConditionOpEnum op = expr.getCondition();

        // 执行比较逻辑
        switch (op) {
            case EQUAL:
                return Objects.equals(String.valueOf(left), right);
            case NOT_EQUAL:
                return !Objects.equals(String.valueOf(left), right);
            case NULL:
                return left == null;
            case NOT_NULL:
                return left != null;
            case INCLUDE:
                return left != null && String.valueOf(left).contains(right);
            case NOT_INCLUDE:
                return left != null && !String.valueOf(left).contains(right);
            case GREATER_THAN:
                return compare(left, right) > 0;
            case GREATER_THAN_OR_EQUAL:
                return compare(left, right) >= 0;
            case LESS_THAN:
                return compare(left, right) < 0;
            case LESS_THAN_OR_EQUAL:
                return compare(left, right) <= 0;
            default:
                return false;
        }
    }

    /**
     * 按引用路径从上下文中递归获取目标值
     */
    private static String resolveQuotePath(JSONObject context, List<String> path) {
        if (path == null || path.size() < 2) {
            return null;
        }

        Object current = context;
        for (int i = 2; i < path.size(); i++) {
            if (current instanceof JSONObject) {
                current = ((JSONObject) current).get(path.get(i));
            } else if (current instanceof Map) {
                current = ((Map<?, ?>) current).get(path.get(i));
            } else {
                return null;
            }
        }

        return current != null ? String.valueOf(current) : null;
    }

    /**
     * 数值比较
     */
    private static int compare(Object left, String right) {
        try {
            double leftValue = Double.parseDouble(String.valueOf(left));
            double rightValue = Double.parseDouble(right);
            return Double.compare(leftValue, rightValue);
        } catch (Exception e) {
            return 0;
        }
    }
}
