/**
 * streams-bridge — proxy data-stream signals into A2UI surface data
 * models (per OD-CHART-16 option b).
 *
 * The bridge duck-types the renderer (it needs `.process()`, nothing
 * else), so it works with any A2UI-protocol consumer — the actual
 * `A2UIRenderer` from `@adia-ai/a2ui-runtime`, a custom renderer, or
 * a test stub.
 *
 * Contract:
 *  - One-way only: stream → data model. A2UI writes back to its model
 *    (e.g. via `update-data-model` wiring actions) do NOT propagate
 *    into the stream signal.
 *  - Tear down with the returned dispose function. Dispose detaches
 *    the effect; it does NOT release the stream's refcount.
 *  - `select` uses dot-separated path syntax (matches
 *    `data-stream-path` on the trait). `path` uses slash-separated
 *    syntax (matches A2UI bindings).
 *
 * Runtime exports mirror `core/streams-bridge.js`. `.d.ts` authored in
 * v0.5.6 §191 to close the §178 audit-script baseline missing-sibling
 * gap.
 *
 * @see ./streams-bridge.js (runtime SoT)
 * @see ./data-stream.js (the stream registry the bridge reads from)
 */

/**
 * Minimal renderer contract the bridge requires. The actual
 * `A2UIRenderer` from `@adia-ai/a2ui-runtime` satisfies this surface,
 * as does any custom renderer that handles
 * `{ type: 'updateDataModel', ... }` actions.
 */
export interface BridgeRenderer {
  process(action: {
    type: 'updateDataModel';
    surfaceId: string;
    path: string;
    value: unknown;
  }): void;
}

/**
 * Bridge options shared by {@link bridgeStream} and
 * {@link bridgeStreamAsync}.
 */
export interface BridgeOptions {
  /** Target surface ID inside the renderer's data model. */
  surfaceId: string;
  /** Stream registry ID (the same string passed to `acquireStream`). */
  streamId: string;
  /** Slash-separated A2UI data-model path inside the surface. */
  path: string;
  /** Optional dot-separated path to a sub-value within the stream's signal value. */
  select?: string;
}

/**
 * Bridge a registered stream into a renderer's surface data model.
 *
 * If the stream is not yet registered, logs a warning and returns a
 * no-op dispose. Use {@link bridgeStreamAsync} when the stream might
 * register after this call (e.g. DOM source connecting on the same
 * tick as the bridge wiring).
 *
 * Returns a dispose function — call it to detach the effect.
 */
export function bridgeStream(renderer: BridgeRenderer, opts: BridgeOptions): () => void;

/**
 * Async variant — awaits the stream's registration before attaching
 * the effect. Resolves once the bridge is wired (the resolved value
 * is the dispose function).
 */
export function bridgeStreamAsync(
  renderer: BridgeRenderer,
  opts: BridgeOptions,
): Promise<() => void>;
