/**
 * Server-facing types for the I/O ops (`read`, `write`, `getThumbnail`).
 *
 * These differ from the wire schemas in `schemas/ops.ts` so user-supplied
 * handlers see clean, typed values (`Uint8Array`, `ReadableStream`) instead
 * of base64 strings and opaque transfer ids. The dispatcher in
 * `server/handler.ts` adapts between the two.
 */

import type { ThumbnailSize, WriteResult } from '../schemas/ops.js';

// ─── read handler types ──────────────────────────────────────

/**
 * Value returned by a user-supplied `read` handler.
 *
 *  - `inline`: the bytes are returned in-band; the dispatcher base64-encodes
 *    them and computes the sha256 if the user did not provide one. Inline
 *    reads MUST be ≤ 256 KiB plaintext.
 *  - `streams`: the user provides a `ReadableStream`, the declared `size`,
 *    and a precomputed `sha256` (e.g. cached on the file's metadata row).
 *    The dispatcher initiates an outbound `@shade/transfer` transfer and
 *    echoes the transfer's `streamId` back to the client over RPC so the
 *    client-side bridge can subscribe.
 */
export type UserReadResult =
  | UserReadResultInline
  | UserReadResultStreams;

export interface UserReadResultInline {
  kind: 'inline';
  bytes: Uint8Array;
  /** Optional — dispatcher computes if absent. */
  sha256?: string;
  contentType?: string;
}

export interface UserReadResultStreams {
  kind: 'streams';
  stream: ReadableStream<Uint8Array>;
  size: number;
  /** REQUIRED — the dispatcher cannot synchronously hash a stream. */
  sha256: string;
  contentType?: string;
}

// ─── write handler types ─────────────────────────────────────

/**
 * Value passed to a user-supplied `write` handler.
 *
 * The dispatcher decodes the wire `WriteArgs` and (for `streams`) parks
 * the inbound transfer via the streams-bridge, then synthesizes this
 * cleaner shape for the user.
 */
export interface UserWriteArgs {
  path: string;
  contentType?: string;
  overwrite: boolean;
  content: UserWriteContent;
}

export type UserWriteContent =
  | UserWriteContentInline
  | UserWriteContentStreams;

export interface UserWriteContentInline {
  kind: 'inline';
  bytes: Uint8Array;
  size: number;
  /** sha256 of `bytes`, computed by the dispatcher. */
  sha256: string;
}

export interface UserWriteContentStreams {
  kind: 'streams';
  /** Plaintext stream. Closes when the inbound `@shade/transfer` completes. */
  stream: ReadableStream<Uint8Array>;
  /** Declared plaintext size from the client's RPC args. */
  size: number;
  /**
   * Promise that resolves with the transfer-verified sha256 once the entire
   * stream has been received. Use this to attach a content hash to the
   * user's storage record.
   */
  sha256: Promise<string>;
}

// ─── getThumbnail handler types ──────────────────────────────

/** Value returned by a user-supplied `getThumbnail` handler. */
export interface UserThumbnailResult {
  bytes: Uint8Array;
  format: 'png' | 'webp' | 'jpeg';
  width: number;
  height: number;
  /** Optional — dispatcher computes if absent. */
  sha256?: string;
}

// ─── Re-exports ──────────────────────────────────────────────
export type { ThumbnailSize, WriteResult };
