import { fetchJson } from "@/api/client";

export interface AgentObserverRunPageQuery {
  page: number;
  pageSize: number;
  status?: string;
  projectId?: string;
  workspace?: string;
  backendProfile?: string;
  providerId?: string;
  search?: string;
  updatedAfter?: string;
  sort?: string;
}

export interface AgentObserverRunPagePayload {
  items: Array<Record<string, unknown>>;
  page: number;
  pageSize: number;
  total: number;
  totalPages: number;
  hasNextPage: boolean;
  facets: Record<string, unknown>;
  authority: string;
  elapsedMs: number;
  valuesPrinted: false;
}

export async function fetchAgentObserverRuns(query: AgentObserverRunPageQuery) {
  const search = new URLSearchParams({ page: String(query.page), pageSize: String(query.pageSize) });
  if (query.status) search.set("status", query.status);
  if (query.projectId) search.set("projectId", query.projectId);
  if (query.workspace) search.set("workspace", query.workspace);
  if (query.backendProfile) search.set("backendProfile", query.backendProfile);
  if (query.providerId) search.set("providerId", query.providerId);
  if (query.search) search.set("search", query.search);
  if (query.updatedAfter) search.set("updatedAfter", query.updatedAfter);
  if (query.sort) search.set("sort", query.sort);
  return await fetchJson<AgentObserverRunPagePayload>(`/v1/agent-observer/runs?${search.toString()}`, {
    timeoutMs: 10_000,
    timeoutName: "AgentRun 分页快照",
  });
}

export interface AgentObserverStreamCallbacks {
  afterId?: string | null;
  liveOnly?: boolean;
  onEnvelope: (payload: unknown, eventId: string | null) => void;
  onHandoff: (payload: unknown) => void;
  onConnected: (payload: unknown) => void;
  onHeartbeat: (payload: unknown) => void;
  onStreamError: (payload: unknown) => void;
  onTransportError: () => void;
}

export function openAgentObserverStream(callbacks: AgentObserverStreamCallbacks): EventSource {
  const url = new URL("/v1/agent-observer/events", window.location.origin);
  if (callbacks.afterId) url.searchParams.set("afterId", callbacks.afterId);
  if (callbacks.liveOnly) url.searchParams.set("mode", "live");
  const source = new EventSource(`${url.pathname}${url.search}`, { withCredentials: true });
  source.addEventListener("hwlab.event.v1", (event) => callbacks.onEnvelope(parseEvent(event), event instanceof MessageEvent ? event.lastEventId || null : null));
  source.addEventListener("agent-observer.handoff", (event) => callbacks.onHandoff(parseEvent(event)));
  source.addEventListener("agent-observer.connected", (event) => callbacks.onConnected(parseEvent(event)));
  source.addEventListener("agent-observer.heartbeat", (event) => callbacks.onHeartbeat(parseEvent(event)));
  source.addEventListener("agent-observer.error", (event) => callbacks.onStreamError(parseEvent(event)));
  source.onerror = () => callbacks.onTransportError();
  return source;
}

function parseEvent(event: Event): unknown {
  if (!(event instanceof MessageEvent) || typeof event.data !== "string") return null;
  try {
    return JSON.parse(event.data);
  } catch {
    return null;
  }
}
