/**
 * Domain types for the chatbot widget — deliberately decoupled from
 * the proto-derived types under `apps/portal-bff/src/grpc/gen/`.
 *
 * The widget consumes the BFF's SSE wire format (per
 * [ADR-0024](../../../../../../docs/decisions/0024-ai-service-relay-grpc-sse-bridge.md)),
 * not the gRPC stubs themselves; sharing the gRPC stubs across the
 * boundary would pull `@grpc/grpc-js` and `@bufbuild/protobuf` into
 * the SPA bundle (~100 KB) for no functional gain. Keeping the
 * widget on a TypeScript-only shape that mirrors the SSE JSON
 * payloads costs ~30 lines of redeclaration and keeps the SPA
 * lean.
 */

/** Two roles the SPA can author. The BFF constructs tool messages. */
export type ChatMessageRole = 'user' | 'assistant';

export type ChatbotView = 'closed' | 'windowed' | 'fullscreen';

export interface CitationRef {
  /** Locally-assigned 1-based index used as the [n] footnote token. */
  readonly index: number;
  readonly chunkId: string;
  readonly documentId: string;
  readonly source: string;
  readonly score: number;
  readonly snippet: string;
}

export interface ChatbotMessage {
  /** Stable id for `track` in the message-list template. */
  readonly id: string;
  readonly role: ChatMessageRole;
  /** Streamed content — grows as the SSE stream arrives. */
  readonly content: string;
  readonly citations: ReadonlyArray<CitationRef>;
  /**
   * When set, the message ended in an error (relay or upstream).
   * The chat bubble renders an inline `role="alert"` banner.
   */
  readonly errorCode?: string;
  readonly errorMessage?: string;
  /** True after the terminal `done` SSE frame (or after an error). */
  readonly done: boolean;
}

/** Shape of the SSE bridge's `event: token` payload. */
export interface TokenFramePayload {
  readonly token?: string;
  readonly value?: string;
}

/** Shape of `event: citation`. */
export interface CitationFramePayload {
  readonly chunkId: string;
  readonly documentId: string;
  readonly source: string;
  readonly score: number;
  readonly snippet: string;
}

/** Shape of `event: error`. */
export interface ErrorFramePayload {
  readonly code: string;
  readonly message: string;
  readonly retriable: boolean;
}

/** Shape of `event: done`. */
export interface DoneFramePayload {
  readonly stats?: {
    readonly tokensIn?: number;
    readonly tokensOut?: number;
    readonly chunksRetrieved?: number;
  };
}
