/**
 * Public types for @shade/streams.
 *
 * Higher-level wrappers for transfer-orchestration (parallel lanes, resume,
 * progress, etc.) live in @shade/transfer.
 */

/**
 * Allow-listed thumbnail MIME types (V3.9). The receiver MUST refuse to
 * render thumbnails declaring a MIME outside this set so a hostile sender
 * cannot smuggle exotic formats past the preview-renderer.
 */
export const THUMBNAIL_MIME_ALLOWLIST = [
  'image/jpeg',
  'image/webp',
  'image/png',
] as const;
export type ThumbnailMime = (typeof THUMBNAIL_MIME_ALLOWLIST)[number];

/**
 * Hard cap on a thumbnail stream's plaintext size (V3.9). 64 KiB covers a
 * 256x256 high-quality WebP/JPEG with headroom; oversized declarations are
 * rejected before any bytes hit the receiver's renderer.
 */
export const THUMBNAIL_MAX_BYTES = 64 * 1024;

/**
 * Optional E2EE file metadata (V3.9). Carried inside the existing
 * `stream-init` control envelope plaintext; backwards-compatible — older
 * receivers that do not understand the field simply ignore it.
 *
 * Bytes that are sensitive (`filename`, `mimeType`) ride inside the
 * Double Ratchet plaintext, so the server only ever sees the bin'd
 * `totalBytes`. The thumbnail itself is shipped as a *separate* stream
 * (with id `${mainStreamId}.thumb`) keyed independently so a server
 * compromise leaks neither preview pixels nor declared filename.
 */
export interface StreamFileMetadata {
  /** Original filename. E2EE — never visible to the server. */
  filename?: string;
  /** Content MIME type (e.g. `application/pdf`). E2EE. */
  mimeType?: string;
  /**
   * base64url streamId of the companion thumbnail stream. Receivers use
   * this to correlate the inbound thumbnail transfer with this main
   * transfer. Always shipped alongside `thumbnailHash` /
   * `thumbnailMime` / `thumbnailBytes`.
   */
  thumbnailStreamId?: string;
  /** sha256 of the separate thumbnail-stream's plaintext, base64. */
  thumbnailHash?: string;
  /** Declared MIME of the thumbnail stream (must be in `THUMBNAIL_MIME_ALLOWLIST`). */
  thumbnailMime?: ThumbnailMime;
  /** Declared plaintext byte length of the thumbnail (≤ `THUMBNAIL_MAX_BYTES`). */
  thumbnailBytes?: number;
}

/** Plaintext metadata sent in a stream-init control envelope. */
export interface StreamMetadata {
  name?: string;
  /** Total plaintext size in bytes. Omit for streams of unknown length. */
  sizeBytes?: number;
  contentType?: string;
  /** Plaintext bytes per chunk for this stream. */
  chunkSize: number;
  /** Total chunk count across all lanes. Omit for unknown-length streams. */
  totalChunks?: number;
  /** Sender's local clock at init time (advisory; never used for security decisions). */
  sentAt: number;
  /**
   * Optional application-level metadata, JSON-stringified-safe key/value
   * pairs. Round-tripped verbatim through stream-init plaintext. Used by
   * higher layers (e.g. `@shade/files` writes a `shadeFilesWriteId` here so
   * a server-side bridge can correlate an inbound transfer with a pending
   * RPC). The transport itself does not interpret these values.
   */
  userMetadata?: Record<string, string>;
  /**
   * V3.9 — optional E2EE file metadata. Older receivers ignore this field;
   * widgets and `@shade/files` consult it to render filename / preview.
   */
  fileMetadata?: StreamFileMetadata;
}

/** Per-lane partition assignment carried in stream-init. */
export type LanePartition =
  | {
      kind: 'range';
      /** Inclusive start byte of this lane's slice. */
      startByte: number;
      /** Exclusive end byte of this lane's slice. */
      endByte: number;
      /** First chunk seq this lane's region begins at (always 0 for per-lane numbering). */
      startChunk: number;
    }
  | {
      kind: 'round-robin';
      /** Chunk i goes to lane (i mod count). */
      lane: number;
      count: number;
    };

/** Per-lane state included in stream-init plaintext. laneKey is NOT shipped — it is derived. */
export interface LaneInitSpec {
  laneId: number;
  partition: LanePartition;
}

import type { StreamChunkWire } from '@shade/proto';

/** Wire-decoded stream-chunk envelope (alias for @shade/proto's `StreamChunkWire`). */
export type StreamChunkEnvelope = StreamChunkWire;

/** Result returned from `StreamSender.encryptChunk`. */
export interface EncryptedChunk {
  envelope: StreamChunkEnvelope;
  /** Raw bytes ready to ship — output of `encodeStreamChunk`. */
  bytes: Uint8Array;
  seq: number;
}

/** Result returned from `StreamReceiver.decryptChunk`. */
export interface DecryptedChunk {
  plaintext: Uint8Array;
  seq: number;
  isLast: boolean;
}
