package com.agent.management.engine;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 单个节点执行结果
 */
public class NodeExecutionResult {

    public enum Status { RUNNING, SUCCESS, FAILED, SKIPPED, NO_RUN }

    private final String nodeId;
    private final Status status;
    private final Map<String, Object> output;
    private final String error;
    private final String selectedBranch; // 条件节点选中分支的 sourceHandle
    private final List<ExecutionLog> logs; // 执行过程日志
    /** 执行后完整 variables 快照，用于 debug 视图与运行历史回放。null 表示未采集（如失败/跳过的节点）。 */
    private final Map<String, Object> contextSnapshot;
    /**
     * 本次执行的 Visit 唯一标识。引擎在 executeOneNode 入口预生成 UUID 并绑定到 result，
     * 让前端能将 node_stream / node_status 事件按 visitUuid 路由到具体 Visit 卡片。
     * null 表示未关联（向后兼容旧测试 / 一次性 result）。
     */
    private final String visitUuid;

    private NodeExecutionResult(String nodeId, Status status, Map<String, Object> output,
                                String error, String selectedBranch, List<ExecutionLog> logs,
                                Map<String, Object> contextSnapshot) {
        this(nodeId, status, output, error, selectedBranch, logs, contextSnapshot, null);
    }

    private NodeExecutionResult(String nodeId, Status status, Map<String, Object> output,
                                String error, String selectedBranch, List<ExecutionLog> logs,
                                Map<String, Object> contextSnapshot, String visitUuid) {
        this.nodeId = nodeId;
        this.status = status;
        this.output = output;
        this.error = error;
        this.selectedBranch = selectedBranch;
        this.logs = logs != null ? logs : Collections.emptyList();
        this.contextSnapshot = contextSnapshot;
        this.visitUuid = visitUuid;
    }

    public static NodeExecutionResult success(String nodeId, Map<String, Object> output) {
        return new NodeExecutionResult(nodeId, Status.SUCCESS, output, null, null, null, null);
    }

    public static NodeExecutionResult success(String nodeId, Map<String, Object> output, List<ExecutionLog> logs) {
        return new NodeExecutionResult(nodeId, Status.SUCCESS, output, null, null, logs, null);
    }

    public static NodeExecutionResult success(String nodeId, Map<String, Object> output, String selectedBranch) {
        return new NodeExecutionResult(nodeId, Status.SUCCESS, output, null, selectedBranch, null, null);
    }

    public static NodeExecutionResult failed(String nodeId, String error) {
        return new NodeExecutionResult(nodeId, Status.FAILED, null, error, null, null, null);
    }

    public static NodeExecutionResult failed(String nodeId, String error, List<ExecutionLog> logs) {
        return new NodeExecutionResult(nodeId, Status.FAILED, null, error, null, logs, null);
    }

    public static NodeExecutionResult skipped(String nodeId) {
        return new NodeExecutionResult(nodeId, Status.SKIPPED, Collections.emptyMap(), null, null, null, null);
    }

    public static NodeExecutionResult noRun(String nodeId) {
        return new NodeExecutionResult(nodeId, Status.NO_RUN, Collections.emptyMap(), null, null, null, null);
    }

    /**
     * 在已有 result 上附加上下文快照，返回新实例（不可变对象模式）。
     * 用于引擎在节点完成后补全快照信息。
     */
    public NodeExecutionResult withContextSnapshot(Map<String, Object> snapshot) {
        return new NodeExecutionResult(nodeId, status, output, error, selectedBranch, logs, snapshot, visitUuid);
    }

    /**
     * 在已有 result 上附加 visitUuid，返回新实例（不可变对象模式）。
     * 用于引擎在 executeOneNode 入口生成 visitUuid 后绑定到 result。
     */
    public NodeExecutionResult withVisitUuid(String visitUuid) {
        return new NodeExecutionResult(nodeId, status, output, error, selectedBranch, logs, contextSnapshot, visitUuid);
    }

    public String getNodeId() { return nodeId; }
    public Status getStatus() { return status; }
    public Map<String, Object> getOutput() { return output; }
    public String getError() { return error; }
    public String getSelectedBranch() { return selectedBranch; }
    public List<ExecutionLog> getLogs() { return logs; }
    public Map<String, Object> getContextSnapshot() { return contextSnapshot; }
    public String getVisitUuid() { return visitUuid; }
}
