package com.easyagents.agent.runtime.event.observer;

import com.easyagents.agent.runtime.event.AgentRuntimeEvent;
import com.easyagents.agent.runtime.event.AgentRuntimeEventBridge;
import com.easyagents.agent.runtime.event.AgentRuntimeEventType;
import com.easyagents.agent.runtime.event.AgentRuntimeObserver;
import io.agentscope.core.agent.Agent;
import io.agentscope.core.hook.ErrorEvent;
import io.agentscope.core.hook.HookEvent;
import reactor.core.publisher.Mono;

/**
 * 监听 AgentScope 原生错误事件，并发射运行失败旁路事件。
 *
 * <p>该观察器复用 {@link AgentRuntimeEventType#FAILED}，但通过 payload 中的
 * {@code source=HOOK} 标识它来自 AgentScope 生命周期观察，不等同于 Easy-Agents
 * runtime 外层流已经完成失败收口。</p>
 */
public class AgentRuntimeErrorObserver implements AgentRuntimeObserver {

    private final AgentRuntimeEventBridge eventBridge;

    /**
     * 创建运行错误观察器。
     *
     * @param eventBridge 旁路事件桥
     */
    public AgentRuntimeErrorObserver(AgentRuntimeEventBridge eventBridge) {
        this.eventBridge = eventBridge;
    }

    /**
     * 观察 AgentScope 错误事件。
     *
     * @param event AgentScope Hook 事件
     * @return 完成信号
     */
    @Override
    public Mono<Void> observe(HookEvent event) {
        if (!(event instanceof ErrorEvent errorEvent)) {
            return Mono.empty();
        }
        Throwable error = errorEvent.getError();
        AgentRuntimeEvent runtimeEvent = eventBridge.event(AgentRuntimeEventType.FAILED);
        runtimeEvent.getPayload().put("source", "HOOK");
        runtimeEvent.getPayload().put("phase", "ERROR");
        runtimeEvent.getPayload().put("stage", "AGENTSCOPE_HOOK");
        runtimeEvent.getPayload().put("errorType", error == null ? null : error.getClass().getName());
        runtimeEvent.getPayload().put("message", error == null ? "AgentScope hook error." : error.getMessage());
        appendAgent(runtimeEvent, errorEvent.getAgent());
        eventBridge.emit(runtimeEvent);
        return Mono.empty();
    }

    private void appendAgent(AgentRuntimeEvent event, Agent agent) {
        if (agent == null) {
            return;
        }
        event.getPayload().put("agentName", agent.getName());
        event.getPayload().put("agentScopeAgentId", agent.getAgentId());
    }
}
