// Test helpers: build JSON + SSE Response objects and a typed fetch mock.

export function jsonResponse(body: unknown, status = 200): Response {
  return new Response(JSON.stringify(body), {
    status,
    headers: { 'content-type': 'application/json' }
  });
}

export function emptyResponse(status = 200): Response {
  return new Response(null, { status });
}

/** Build a text/event-stream Response from raw SSE frame strings. */
export function sseResponse(frames: string[], status = 200): Response {
  const encoder = new TextEncoder();
  const stream = new ReadableStream<Uint8Array>({
    start(controller) {
      for (const frame of frames) controller.enqueue(encoder.encode(frame));
      controller.close();
    }
  });
  return new Response(stream, {
    status,
    headers: { 'content-type': 'text/event-stream' }
  });
}

/** One SSE `data:` event frame for a realtime payload. */
export function dataFrame(topic: string, message: unknown, publishedAt = '2026-06-04T00:00:00Z'): string {
  const payload = JSON.stringify({ topic, message, published_at: publishedAt });
  return `data: ${payload}\n\n`;
}

export type FetchArgs = [string | URL | Request, RequestInit?];

type MockLike = { mock: { calls: ReadonlyArray<ReadonlyArray<unknown>> } };

export function lastInit(mock: MockLike, i = 0): RequestInit {
  const call = mock.mock.calls[i];
  if (!call) throw new Error(`no fetch call at index ${i}`);
  return (call[1] as RequestInit | undefined) ?? {};
}

export function lastUrl(mock: MockLike, i = 0): string {
  const call = mock.mock.calls[i];
  if (!call) throw new Error(`no fetch call at index ${i}`);
  return String(call[0]);
}

export function headerOf(init: RequestInit, name: string): string | undefined {
  const h = init.headers as Record<string, string> | undefined;
  return h?.[name];
}
