// Public types for the chat-audio subsystem.

export type ChatAudioEvent =
  | 'messageSent'
  | 'messageReceived'
  | 'streamStart'
  | 'error'
  | 'mention'
  | 'notification';

/** Map an event to a sound URL. `false` silences the event explicitly. */
export type ChatAudioSounds = Partial<Record<ChatAudioEvent, string | false>>;

export interface ChatAudioConfig {
  /** Map event → asset URL. Omit (or set `false`) to silence one event. */
  sounds?: ChatAudioSounds;
  /** Master volume 0..1. Persisted via the global prefs store. */
  volume?: number;
  /**
   * Per-event volume multipliers (0..1). Applied on top of `volume`.
   * Defaults applied by `useChatAudio` if not provided:
   *   - error: 0.25  (gentle — error UI is the loud signal, not the sound)
   *   - mention: 1.0 (louder than baseline received)
   *   - messageSent: 0.5  (subtle self-confirmation)
   *   - messageReceived: 0.7
   *   - streamStart: 0.3  (very subtle, fires often)
   *   - notification: 0.9
   *
   * Pass `{}` to disable defaults; pass overrides to tweak.
   */
  eventVolumes?: Partial<Record<ChatAudioEvent, number>>;
  /** Master mute. */
  muted?: boolean;
  /** Custom predicate — return `false` to suppress a play call. */
  shouldPlay?: (event: ChatAudioEvent) => boolean;
  /** Default-suppress when user prefers reduced motion. Default: true. */
  respectReducedMotion?: boolean;
  /** Default-suppress when user prefers reduced data. Default: true. */
  respectReducedData?: boolean;
  /** Mute when host page is hidden (`visibilityState === 'hidden'`). Default: true. */
  muteWhenHidden?: boolean;
  /**
   * Skip web playback entirely — `play()` becomes a no-op. Pair with
   * `onSoundEvent` for native hosts (cmdop_go / Tauri) that play sounds
   * outside the browser.
   */
  silenced?: boolean;
  /**
   * Side-channel fired whenever `play(event)` is called. Stays active
   * even when `silenced=true`. Use to bridge into a native audio backend.
   */
  onSoundEvent?: (event: ChatAudioEvent) => void;
}

export interface UseChatAudioReturn {
  /** Play a sound for an event. No-ops if the event has no URL or is muted. */
  play: (event: ChatAudioEvent) => void;
  /** Eagerly load an event's audio (called automatically on mount). */
  preload: (event: ChatAudioEvent) => void;
  /** Manually unlock — useful in stories/tests. */
  unlock: () => void;
  /** True after the first user gesture inside the chat root. */
  isUnlocked: boolean;
  /** Master mute (persistent). */
  muted: boolean;
  setMuted: (m: boolean) => void;
  /** Flip mute state — convenience. */
  toggleMute: () => void;
  /** Master volume 0..1 (persistent). */
  volume: number;
  setVolume: (v: number) => void;
  /** Per-event opt-out (persistent). */
  isEventEnabled: (event: ChatAudioEvent) => boolean;
  setEventEnabled: (event: ChatAudioEvent, enabled: boolean) => void;
  /** True when no sounds are configured (or `silenced`). */
  isSilent: boolean;
}
