package com.easyagents.agent.runtime.event;

import io.agentscope.core.hook.HookEvent;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * AgentScope Hook 事件的统一观察和干预调度器。
 *
 * <p>处理顺序固定为：先执行干预器，再执行观察器。干预器属于主线路能力，
 * 可以修改 AgentScope HookEvent；观察器属于旁线路能力，只能查看事件并通过
 * {@link AgentRuntimeEventBridge} 发射对外监察事件。</p>
 */
public class AgentRuntimeObservationManager {

    private final List<AgentRuntimeInterceptor> interceptors;
    private final List<AgentRuntimeObserver> observers;

    /**
     * 创建观察调度器。
     *
     * @param interceptors 主线路干预器
     * @param observers 旁路观察器
     */
    public AgentRuntimeObservationManager(List<AgentRuntimeInterceptor> interceptors,
                                          List<AgentRuntimeObserver> observers) {
        this.interceptors = sortInterceptors(interceptors);
        this.observers = sortObservers(observers);
    }

    /**
     * 创建空观察调度器。
     *
     * @return 空调度器
     */
    public static AgentRuntimeObservationManager empty() {
        return new AgentRuntimeObservationManager(List.of(), List.of());
    }

    /**
     * 处理 AgentScope Hook 事件。
     *
     * @param event Hook 事件
     * @param <T> Hook 事件类型
     * @return 处理后的 Hook 事件
     */
    public <T extends HookEvent> Mono<T> handle(T event) {
        Mono<T> chain = Mono.just(event);
        for (AgentRuntimeInterceptor interceptor : interceptors) {
            chain = chain.flatMap(interceptor::intercept);
        }
        for (AgentRuntimeObserver observer : observers) {
            chain = chain.flatMap(current -> observer.observe(current).thenReturn(current));
        }
        return chain;
    }

    private List<AgentRuntimeInterceptor> sortInterceptors(List<AgentRuntimeInterceptor> source) {
        List<AgentRuntimeInterceptor> sorted = new ArrayList<>(source == null ? List.of() : source);
        sorted.sort(Comparator.comparingInt(AgentRuntimeInterceptor::priority));
        return List.copyOf(sorted);
    }

    private List<AgentRuntimeObserver> sortObservers(List<AgentRuntimeObserver> source) {
        List<AgentRuntimeObserver> sorted = new ArrayList<>(source == null ? List.of() : source);
        sorted.sort(Comparator.comparingInt(AgentRuntimeObserver::priority));
        return List.copyOf(sorted);
    }
}
