package com.agent.management.engine;

import com.agent.management.model.entity.WorkflowRunVisit;

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

/**
 * 工作流执行 SSE 事件
 */
public class WorkflowRunEvent {

    private final String runId;
    private final String type;   // node_status, node_stream, workflow_complete, workflow_error,
                                 // visit_recorded, planner_decision (AGENTIC 模式)
    private final String nodeId;
    /**
     * 本次节点执行（Visit）的唯一标识。
     * <p>DAG / AGENTIC 模式下，引擎在 executeOneNode 入口预生成 visitUuid 并绑定到所有
     * node_status / node_stream 事件，让前端能按 visitUuid 路由到具体 Visit 卡片，
     * 而非按 nodeId 聚合（同节点多次访问时 nodeId 会冲突）。</p>
     * <p>null 表示未关联（visit_recorded / planner_decision / workflow_complete 等不需要）。</p>
     */
    private final String visitUuid;
    private final String status; // RUNNING, SUCCESS, FAILED, SKIPPED
    private final Object output;
    private final String error;
    private final Boolean success;
    private final List<ExecutionLog> logs;
    /** 节点执行后的完整 variables 快照（debug 视图，仅 node_status SUCCESS 携带） */
    private final Map<String, Object> contextSnapshot;
    // node_stream 事件专用字段
    // v1.1 kind 扩展：thinking | tool_call | tool_result | status | step | tool_progress | todo_update | clarify_request
    private final String kind;
    private final String content;   // 增量内容
    private final String toolName;  // 工具名（kind != tool_* 时为 null）
    /** workflow_complete 携带的工作空间文件列表（与 WorkflowRun.workingDirFiles 同源，便于前端实时展示） */
    private final List<String> workingDirFiles;
    /** visit_recorded 事件携带的 Visit 快照（DAG / AGENTIC 模式统一） */
    private final WorkflowRunVisit visit;
    /** planner_decision 事件携带的 AI 决策（AGENTIC 模式专用） */
    private final PlannerService.PlannerDecision decision;

    private WorkflowRunEvent(String runId, String type, String nodeId, String status,
                             Object output, String error, Boolean success, List<ExecutionLog> logs) {
        this(runId, type, nodeId, null, status, output, error, success, logs,
                null, null, null, null, null, null, null);
    }

    private WorkflowRunEvent(String runId, String type, String nodeId, String visitUuid, String status,
                             Object output, String error, Boolean success, List<ExecutionLog> logs,
                             Map<String, Object> contextSnapshot,
                             String kind, String content, String toolName,
                             List<String> workingDirFiles,
                             WorkflowRunVisit visit,
                             PlannerService.PlannerDecision decision) {
        this.runId = runId;
        this.type = type;
        this.nodeId = nodeId;
        this.visitUuid = visitUuid;
        this.status = status;
        this.output = output;
        this.error = error;
        this.success = success;
        this.logs = logs;
        this.contextSnapshot = contextSnapshot;
        this.kind = kind;
        this.content = content;
        this.toolName = toolName;
        this.workingDirFiles = workingDirFiles;
        this.visit = visit;
        this.decision = decision;
    }

    /** node_status RUNNING：visitUuid 由 executeOneNode 入口预生成后注入 */
    public static WorkflowRunEvent nodeRunning(String runId, String nodeId, String visitUuid) {
        return new WorkflowRunEvent(runId, "node_status", nodeId, visitUuid, "RUNNING",
                null, null, null, null, null, null, null, null, null, null, null);
    }

    /** 向后兼容：无 visitUuid 的入口（逐渐弃用） */
    public static WorkflowRunEvent nodeRunning(String runId, String nodeId) {
        return nodeRunning(runId, nodeId, null);
    }

    /** node_status SUCCESS/FAILED/SKIPPED：从 result 中提取 visitUuid */
    public static WorkflowRunEvent nodeResult(String runId, NodeExecutionResult result) {
        return new WorkflowRunEvent(runId, "node_status", result.getNodeId(), result.getVisitUuid(),
                result.getStatus().name(), result.getOutput(), result.getError(), null, result.getLogs(),
                result.getContextSnapshot(), null, null, null, null, null, null);
    }

    /**
     * 节点执行过程中的流式增量事件（如 Hermes Agent 的 thinking / 工具调用片段）。
     * 前端应按 visitUuid 聚合累加，而非按 nodeId（同节点多次访问会冲突）。
     */
    public static WorkflowRunEvent nodeStream(String runId, String nodeId, String visitUuid,
                                               String kind, String content, String toolName) {
        return new WorkflowRunEvent(runId, "node_stream", nodeId, visitUuid, null,
                null, null, null, null, null, kind, content, toolName, null, null, null);
    }

    /** 向后兼容：无 visitUuid 的入口（逐渐弃用） */
    public static WorkflowRunEvent nodeStream(String runId, String nodeId, String kind,
                                               String content, String toolName) {
        return nodeStream(runId, nodeId, null, kind, content, toolName);
    }

    public static WorkflowRunEvent workflowComplete(String runId, Map<String, Object> outputs,
                                                    List<String> workingDirFiles) {
        return new WorkflowRunEvent(runId, "workflow_complete", null, null, null,
                outputs, null, true, null, null, null, null, null, workingDirFiles, null, null);
    }

    public static WorkflowRunEvent workflowError(String runId, String error) {
        return new WorkflowRunEvent(runId, "workflow_error", null, null, null,
                null, error, false, null, null, null, null, null, null, null, null);
    }

    /**
     * Visit 节点访问快照已持久化（DAG / AGENTIC 模式统一）。
     * <p>前端按 sortOrder 顺序展示 Visit 链；同一节点多次访问会生成多条事件。
     * 对应设计文档 {@code docs/plans/agentic-workflow-plan.md} §2.5。</p>
     */
    public static WorkflowRunEvent visitRecorded(String runId, WorkflowRunVisit visit) {
        return new WorkflowRunEvent(runId, "visit_recorded", null, null, null,
                null, null, null, null, null, null, null, null, null, visit, null);
    }

    /**
     * AGENTIC 模式专用：Planner AI 决策事件。
     * <p>前端用于展示"AI 决策链"（next + reason）。
     * 与 visit_recorded 配对：每次 visit 之后推送一条 planner_decision 表示下一步去哪。</p>
     */
    public static WorkflowRunEvent plannerDecision(String runId, PlannerService.PlannerDecision decision) {
        return new WorkflowRunEvent(runId, "planner_decision", null, null, null,
                null, null, null, null, null, null, null, null, null, null, decision);
    }

    // Getters (SSE 序列化需要)
    public String getRunId() { return runId; }
    public String getType() { return type; }
    public String getNodeId() { return nodeId; }
    public String getVisitUuid() { return visitUuid; }
    public String getStatus() { return status; }
    public Object getOutput() { return output; }
    public String getError() { return error; }
    public Boolean getSuccess() { return success; }
    public List<ExecutionLog> getLogs() { return logs; }
    public Map<String, Object> getContextSnapshot() { return contextSnapshot; }
    public String getKind() { return kind; }
    public String getContent() { return content; }
    public String getToolName() { return toolName; }
    public List<String> getWorkingDirFiles() { return workingDirFiles; }
    public WorkflowRunVisit getVisit() { return visit; }
    public PlannerService.PlannerDecision getDecision() { return decision; }
}
