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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.test.enums.NodeTypeEnum;
import com.cmvr.test.enums.ParamScope;
import com.cmvr.test.flow.builder.FlowGraph;
import com.cmvr.test.flow.builder.FlowNodeWrapper;
import com.cmvr.test.flow.builder.FlowParamDef;
import com.cmvr.test.flow.context.TaskContext;
import com.cmvr.test.flow.context.TaskInstHolder;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.List;

@Component
@RequiredArgsConstructor
public class FlowNodeParamPreparer {

    private final TaskInstHolder taskInstHolder;

    public JSONObject prepare(FlowGraph graph,
                              FlowNodeWrapper node,
                              TaskNodeExecuteMessage rootMessage) {


        TaskContext ctx = taskInstHolder.getContext(rootMessage.getInstId());

        JSONObject input = getInputParams(graph, node.getNodeParams(), rootMessage);

        // 3 START 节点：用 runParams 覆盖默认参数
        if (node.getNodeType() == NodeTypeEnum.START) {
            JSONObject merged = new JSONObject(input);
            JSONObject runParams = ctx.getRunParams();
            for (String key : runParams.keySet()) {
                // runParams 里有值，就覆盖掉定义里的值
                merged.put(key, runParams.get(key));
            }
            return merged;
        }

        // 4 LOOP 节点：动态计算 loopCount
        if (node.getNodeType() == NodeTypeEnum.LOOP) {
            Object loopNumVal = input.get("loopNum");
            input.put("loopArray", loopNumVal);
            int loopCount = 0;

            // 根据迭代路径找到当前层的集合对象
//            Object target = resolveLoopTarget(loopNumVal, rootMessage.getIterations(), 0);
            Object target = loopNumVal;
            if (target instanceof JSONArray) {
                loopCount = ((JSONArray) target).size();
            } else if (target instanceof Collection) {
                loopCount = ((Collection<?>) target).size();
            } else if (target != null && target.getClass().isArray()) {
                loopCount = Array.getLength(target);
            } else if (target instanceof Number) {
                loopCount = ((Number) target).intValue();
            } else if (target != null) {
                try {
                    String string = target.toString();
                    if (string.startsWith("[")) {
                        JSONArray array = JSON.parseArray(string);
                        loopCount = array.size();
                    }else {
                        loopCount = Integer.parseInt(string);
                    }
                } catch (NumberFormatException e) {
                    throw new GlobalException("loopNum 参数格式错误: " + loopNumVal);
                }
            }

            // 写回 inputParams，供 LoopHandler 使用
            input.put("loopNum", loopCount);
        }

        return input;
    }

    private JSONObject getInputParams(FlowGraph graph, List<FlowParamDef> paramDefList, TaskNodeExecuteMessage rootMessage) {
        JSONObject input = new JSONObject();
        TaskContext ctx = taskInstHolder.getContext(rootMessage.getInstId());
        // 遍历当前节点定义的参数
        for (FlowParamDef param : paramDefList) {
            if (param.getScope() != ParamScope.NODE) continue;

            // 1 静态 input 参数
            if ("input".equals(param.getType())) {
                input.put(param.getName(), param.getInput());
            }

            // 2 引用参数（quote）
            else if ("quote".equals(param.getType()) && CollUtil.isNotEmpty(param.getQuote())) {
                String refNodeId = param.getQuote().get(0);        // 被引用的上游节点 ID
                List<String> path = param.getQuote().subList(2, param.getQuote().size()); // 取值路径

                JSONObject source;
                // 引用的参数是上游的输入还是输出
                // 2.1 引用上游输入参数
                if ("input".equalsIgnoreCase(param.getQuoteType())) {
                    source = ctx.getRunParams();
                    JSONObject def = toJson(graph.getNodeParamsDefs().get(refNodeId));
                    for (String key : def.keySet()) {
                        source.put(key, def.get(key));
                    }
                } else if ("output".equalsIgnoreCase(param.getQuoteType())) {
                    // 2.2 引用上游的 output 参数（运行时实际执行结果）
                    // 用 nodeId + iterations 作为 key，避免覆盖
                    source = ctx.getNodeOutput(refNodeId, rootMessage.getIterations());
                } else {
                    throw new GlobalException("参数应用类型出错！quoteType:" + param.getQuoteType());
                }

                // 按路径取嵌套值，例如 ["result", "image", "url"]
                Object val = findNestedValue(source, path);
                input.put(param.getName(), val);
            }
            if (!CollectionUtil.isEmpty(param.getChildren())) {
                // 添加子参数
                input.put(param.getName(), getInputParams(graph, param.getChildren(), rootMessage));
            }
        }
        return input;
    }


    /**
     * 将参数定义列表中的 input 值构建为 JSONObject
     */
    private JSONObject toJson(List<FlowParamDef> defs) {
        JSONObject result = new JSONObject();
        if (CollUtil.isEmpty(defs)) return result;

        for (FlowParamDef param : defs) {
            if (param.getType().equalsIgnoreCase(ParamScope.INPUT.name())) {
                result.put(param.getName(), param.getInput());
                continue;
            }

            String name = param.getName();
            String type = param.getType();
            Object input = param.getInput();

            if ("Object".equals(type) && CollUtil.isNotEmpty(param.getChildren())) {
                result.put(name, toJson(param.getChildren()));
            } else if ("Array".equals(type) && CollUtil.isNotEmpty(param.getChildren())) {
                JSONArray arr = new JSONArray();
                // 默认数组内只有一个结构体模型
                arr.add(toJson(param.getChildren()));
                result.put(name, arr);
            } else {
                result.put(name, input);
            }
        }

        return result;
    }

    /**
     * JSON 多层路径提取
     */
    private Object findNestedValue(JSONObject source, List<String> path) {
        if (source == null || CollUtil.isEmpty(path)) return null;
        Object curr = source;
        for (String key : path) {
            if (!(curr instanceof JSONObject)) return null;
            curr = ((JSONObject) curr).get(key);
        }
        return curr;
    }

    /**
     * 根据迭代路径（iterations）逐层解析嵌套集合
     *  - iterations = []             → 返回最外层对象
     *  - iterations = [2]            → 返回 list[1]
     *  - iterations = [2,3]          → 返回 list[1][2]
     */
    private Object resolveLoopTarget(Object obj, List<Integer> iterations, int depth) {
        if (obj == null) return null;

        // 已经走到当前循环层，返回目标
        if (depth >= iterations.size()) {
            return obj;
        }

        int idx = iterations.get(depth) - 1;

        if (obj instanceof List) {
            List<?> list = (List<?>) obj;
            if (idx >= 0 && idx < list.size()) {
                return resolveLoopTarget(list.get(idx), iterations, depth + 1);
            }
        } else if (obj instanceof JSONArray) {
            JSONArray arr = (JSONArray) obj;
            if (idx >= 0 && idx < arr.size()) {
                return resolveLoopTarget(arr.get(idx), iterations, depth + 1);
            }
        } else if (obj != null && obj.getClass().isArray()) {
            int length = Array.getLength(obj);
            if (idx >= 0 && idx < length) {
                return resolveLoopTarget(Array.get(obj, idx), iterations, depth + 1);
            }
        }

        // 如果不是集合类型，直接返回
        return obj;
    }
}
