/**
 * AG-UI v1-aligned SSE event helpers (ADR-001, Phase 4).
 *
 * Implements the AG-UI v1 protocol shape — events and typed artifacts — so the
 * same backend can feed the in-app chat and future MCP / external clients.
 * Wire-format remains SSE for browser compatibility.
 *
 * Events:
 *   text_delta       — append text to the current assistant message
 *   tool_start       — model is calling a tool (renders collapsible block)
 *   tool_result      — local handler finished (fills the block)
 *   navigate         — clickable navigation button inline (legacy; prefer the
 *                      navigation_offer artifact below)
 *   artifact         — typed rich object the UI renders inline. See `Artifact`.
 *   done             — terminal event; carries usage + final assistant message id
 *   error            — terminal event; carries error detail
 *
 * SSE wire format per message:
 *
 *   event: <name>
 *   data:  <json>
 *
 *   <blank line>
 */

export interface BBox {
  x: number;
  y: number;
  w: number;
  h: number;
}

/** Inline-rendered, typed payloads. The chat UI renders each kind as a card. */
export type Artifact =
  | {
      kind: "citation";
      chunk_id: string;
      doc_id: string;
      page: number;
      type?: string;
      classification?: string | null;
      bbox?: BBox | null;
      snippet?: string;
      score?: number;
    }
  | {
      kind: "crop_image";
      src: string;             // /api/crop?doc=…&page=…&x=…
      doc_id: string;
      page: number;
      chunk_id?: string;
      alt_en?: string;
      alt_pt?: string;
    }
  | {
      kind: "entity_card";
      entity_class: "person" | "organization" | "location" | "event" | "uap_object" | "vehicle" | "operation" | "concept";
      entity_id: string;
      canonical_name: string;
      total_mentions?: number;
      documents_count?: number;
    }
  | { kind: "evidence_card"; evidence_id: string; title?: string; grade?: string }
  | { kind: "hypothesis_card"; hypothesis_id: string; title?: string; posterior?: number }
  | { kind: "case_card"; case_id: string; title?: string }
  | { kind: "navigation_offer"; target: string; label_en: string; label_pt: string };

export type AGUIEvent =
  | { type: "text_delta"; delta: string }
  | { type: "tool_start"; id: string; name: string; args: Record<string, unknown> }
  | { type: "tool_result"; id: string; result: unknown; durationMs?: number }
  | { type: "navigate"; target: string; label: string }
  | { type: "artifact"; artifact: Artifact }
  | { type: "done"; provider: string; model: string; usage?: Record<string, unknown>; messageId?: string }
  | { type: "error"; message: string };

/**
 * Encode an event into the byte-stream chunks expected by the SSE protocol.
 */
export function encodeEvent(ev: AGUIEvent): Uint8Array {
  const enc = new TextEncoder();
  const json = JSON.stringify(ev);
  return enc.encode(`event: ${ev.type}\ndata: ${json}\n\n`);
}

/**
 * Helper that creates a ReadableStream + a typed `emit()` callback to push
 * events into it. Caller closes the stream by calling `emit({type:"done"})` or
 * `close()`.
 */
export function createEventStream(): {
  stream: ReadableStream<Uint8Array>;
  emit: (ev: AGUIEvent) => void;
  close: () => void;
} {
  let controller!: ReadableStreamDefaultController<Uint8Array>;
  const stream = new ReadableStream<Uint8Array>({
    start(c) {
      controller = c;
    },
  });
  return {
    stream,
    emit(ev) {
      try {
        controller.enqueue(encodeEvent(ev));
      } catch { /* stream closed */ }
    },
    close() {
      try { controller.close(); } catch { /* already closed */ }
    },
  };
}
