// The transcription engine interface: the single abstraction that hides the
// platform-specific Whisper backend (transformers.js on web, whisper.rn on
// native) behind one stable contract. The pure orchestration pipeline
// (pipeline.ts) is written entirely against this interface so it can be unit
// tested with a fake engine and never imports any heavy/native dependency.
//
// IMPORTANT contract detail: `transcribeChunk` returns CHUNK-LOCAL times
// (0-based, relative to the start of the chunk it was handed). The pipeline is
// responsible for offsetting those into absolute media time and stitching the
// overlapping windows together (see pipeline.ts + stitch.ts).

import type {
  Backend,
  ModelId,
  PcmAudio,
  Segment,
  TranscribeOptions,
} from '../types';

/**
 * What an engine discovered about the device it is running on. Used by the UI
 * to gate model choices and to decide whether live-mic capture is available.
 */
export interface EngineCapabilities {
  /** The compute backend the engine resolved to (e.g. 'webgpu', 'cpu'). */
  backend: Backend;
  /** Whether this engine can transcribe from a live microphone stream. */
  supportsLiveMic: boolean;
  /** Largest model we'd recommend running on this device/backend. */
  maxRecommendedModel: ModelId;
}

/**
 * A platform-agnostic Whisper engine. Both `engineImpl.web.ts` and
 * `engineImpl.native.ts` export a singleton `engine` satisfying this.
 */
export interface TranscriptionEngine {
  /** Which platform family this engine targets. */
  readonly platform: 'web' | 'native';

  /** Probe the device. May be async (e.g. WebGPU adapter request). */
  capabilities(): Promise<EngineCapabilities>;

  /**
   * Ensure `modelId` is loaded and ready. `onProgress` (if given) receives a
   * fraction in [0, 1] during download/initialization. Implementations should
   * be idempotent: calling again for an already-loaded model is a no-op.
   */
  loadModel(modelId: ModelId, onProgress?: (p: number) => void): Promise<void>;

  /** Synchronous check: is this model already loaded in memory? */
  isModelLoaded(modelId: ModelId): boolean;

  /**
   * Transcribe a single already-decoded 16 kHz mono chunk.
   * Returns segments with CHUNK-LOCAL times (seconds, 0-based). The caller
   * offsets and stitches; engines must NOT add the chunk's media offset.
   */
  transcribeChunk(audio: PcmAudio, opts: TranscribeOptions): Promise<Segment[]>;
}
