export interface SseEvent {
  eventType: string | null;
  dataRaw: string;
  isDone: boolean;
  dataJson: unknown | null;
  raw: string;
}

export function splitEvents(buf: string): { events: string[]; remainder: string } {
  const normalized = buf.replace(/\r\n/g, "\n");
  const parts = normalized.split("\n\n");
  const remainder = parts.pop() ?? "";
  return { events: parts.map((part) => `${part}\n\n`), remainder };
}

export function parseEvent(rawEvent: string): SseEvent {
  let eventType: string | null = null;
  const dataLines: string[] = [];

  for (const line of rawEvent.replace(/\r\n/g, "\n").split("\n")) {
    if (line.startsWith("event:")) {
      eventType = line.slice("event:".length).trim();
    } else if (line.startsWith("data:")) {
      const data = line.slice("data:".length);
      dataLines.push(data.startsWith(" ") ? data.slice(1) : data);
    }
  }

  const dataRaw = dataLines.join("\n");
  const isDone = dataRaw.trim() === "[DONE]";
  let dataJson: unknown | null = null;
  if (!isDone && dataRaw.length > 0) {
    try {
      dataJson = JSON.parse(dataRaw);
    } catch {
      dataJson = null;
    }
  }

  return { eventType, dataRaw, isDone, dataJson, raw: rawEvent };
}

export function encodeEvent(eventType: string | null, data: unknown): string {
  const lines: string[] = [];
  if (eventType !== null) lines.push(`event: ${eventType}`);
  const serialized = typeof data === "string" ? data : JSON.stringify(data);
  for (const dataLine of serialized.split("\n")) {
    lines.push(`data: ${dataLine}`);
  }
  return `${lines.join("\n")}\n\n`;
}
