/**
 * Transport-metadata assembly.
 *
 * A chat send carries two kinds of metadata:
 *   - static  — fixed per session (locale, slug), set once in config.
 *   - dynamic — recomputed for every send by an optional contributor.
 *
 * The dynamic contributor is what enables "capture-on-submit" features
 * (e.g. a fresh page-context snapshot per message): it runs synchronously
 * at send time, and its result is merged over the static metadata.
 */

/** A function that produces extra metadata, freshly, at send time. */
export type DynamicMetadataFn = () => Record<string, unknown> | undefined;

/**
 * Invoke a dynamic-metadata contributor, swallowing any throw.
 *
 * A contributor that fails (e.g. a snapshot capture errors) must never
 * break a chat send — the send proceeds with the static metadata only.
 */
export function safeDynamicMetadata(
  fn: DynamicMetadataFn,
): Record<string, unknown> | undefined {
  try {
    return fn();
  } catch {
    return undefined;
  }
}

/**
 * Merge the static metadata with a per-send dynamic contributor.
 *
 * Called at each `transport.stream/send` so the contributor runs fresh.
 * Dynamic keys win over static keys on collision. When there is no
 * contributor (or it returns nothing) the static metadata passes
 * through unchanged.
 */
export function resolveSendMetadata(
  staticMetadata: Record<string, unknown> | undefined,
  getDynamic: DynamicMetadataFn | undefined,
): Record<string, unknown> | undefined {
  const dynamic = getDynamic ? safeDynamicMetadata(getDynamic) : undefined;
  if (!dynamic) return staticMetadata;
  return { ...staticMetadata, ...dynamic };
}
