type FetchLike = typeof fetch;

export async function collectAgentObserverRuns({ fetchImpl, url, apiKey, timeoutMs }: {
  fetchImpl: FetchLike;
  url: string;
  apiKey: string;
  timeoutMs: number;
}) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  const startedAt = Date.now();
  try {
    const response = await fetchImpl(url, {
      method: "GET",
      headers: { accept: "application/json", authorization: `Bearer ${apiKey}` },
      signal: controller.signal,
    });
    const body = await response.text();
    let payload: any = null;
    try { payload = body ? JSON.parse(body) : null; } catch { /* handled below */ }
    if (!response.ok || payload?.ok === false) {
      throw observerError(
        text(payload?.error?.code) ?? "agent_observer_request_failed",
        text(payload?.error?.message) ?? `GET /v1/agent-observer/runs returned HTTP ${response.status}.`,
        { httpStatus: response.status, bodyBytes: Buffer.byteLength(body) },
      );
    }
    if (!payload || !Array.isArray(payload.items)) {
      throw observerError("agent_observer_response_invalid", "Agent observer run collection did not return an items array.");
    }
    return {
      ...payload,
      elapsedMs: Date.now() - startedAt,
      returnedRunCount: payload.items.length,
      truncated: payload.hasNextPage === true,
      valuesPrinted: false,
    };
  } catch (error: any) {
    if (controller.signal.aborted && error?.code === undefined) {
      throw observerError("agent_observer_timeout", `Agent observer run collection exceeded ${timeoutMs}ms.`, { timeoutMs });
    }
    throw error;
  } finally {
    clearTimeout(timer);
  }
}

function text(value: unknown): string | null {
  return typeof value === "string" && value.trim() ? value.trim() : null;
}

function observerError(code: string, message: string, details: Record<string, unknown> = {}) {
  return Object.assign(new Error(message), { code, details: { ...details, valuesPrinted: false } });
}
