package com.agent.management.engine;

import lombok.Data;

import java.util.*;

/**
 * 单个节点执行前的工作区视图。
 *
 * <p>包含：
 * <ul>
 *   <li>可直接引用的扁平变量（含节点命名空间变量，如 nodeId__varName）</li>
 *   <li>按节点 ID 隔离的前驱输出（scopedOutputs）</li>
 *   <li>工作空间文件列表</li>
 *   <li>本次运行 ID</li>
 * </ul>
 */
@Data
public class NodeWorkspace {

    /** 可直接通过 {{varName}} 引用的扁平变量表 */
    private final Map<String, Object> variables = new LinkedHashMap<>();

    /** nodeId -> {varName -> value}，用于精确引用某个节点的输出 */
    private final Map<String, Map<String, Object>> scopedOutputs = new LinkedHashMap<>();

    /** 工作空间文件列表（相对路径） */
    private List<String> files = Collections.emptyList();

    /** 本次运行 ID */
    private String runId;

    /**
     * 从扁平变量表中取值。
     */
    public Object getVariable(String name) {
        return variables.get(name);
    }

    /**
     * 从指定节点命名空间中取值。
     *
    * <p>透明穿透 envelope：若 scopedOutputs[nodeId] 是 envelope（含 status/data），
     * 自动从 {@code data} 字段内部取 fieldName，方便调用方无感知地访问业务变量。</p>
     */
    public Object getScopedOutput(String nodeId, String fieldName) {
        Map<String, Object> scoped = scopedOutputs.get(nodeId);
        if (scoped == null) return null;
        if (NodeOutputEnvelope.isEnvelope(scoped)) {
            NodeOutputEnvelope env = NodeOutputEnvelope.fromObject(scoped);
            return env == null ? null : env.getData().get(fieldName);
        }
        return scoped.get(fieldName);
    }

    /**
     * 获取指定节点命名空间的 data 视图（解包 envelope）。
     *
     * <p>用于 NodeInputResolver 的模糊匹配 / JsonPath 提取场景，需要遍历业务字段集合
     * 而不是 envelope 的 status/message/data 三个壳字段。</p>
     *
     * @return envelope 内部 data；若非 envelope 则返回原始 Map；不存在返回 null
     */
    public Map<String, Object> getScopedDataView(String nodeId) {
        Map<String, Object> scoped = scopedOutputs.get(nodeId);
        if (scoped == null) return null;
        if (NodeOutputEnvelope.isEnvelope(scoped)) {
            NodeOutputEnvelope env = NodeOutputEnvelope.fromObject(scoped);
            return env == null ? null : env.getData();
        }
        return scoped;
    }

    /**
     * 获取指定节点 envelope 的状态码（不存在或非 envelope 返回 null）。
     */
    public Integer getScopedStatus(String nodeId) {
        Map<String, Object> scoped = scopedOutputs.get(nodeId);
        if (scoped == null) return null;
        if (NodeOutputEnvelope.isEnvelope(scoped)) {
            NodeOutputEnvelope env = NodeOutputEnvelope.fromObject(scoped);
            return env == null ? null : env.getStatus();
        }
        return null;
    }

    /**
     * 判断变量是否存在。
     */
    public boolean hasVariable(String name) {
        return variables.containsKey(name);
    }
}
