import type { SoundRecipe } from '@/shared/types/audioFiles';

/**
 * Data-driven Web Audio player for a generated sound `recipe`. Mirrors the
 * hardcoded `playBuiltInSound` synthesis, but reads its parameters from the
 * recipe instead of a switch — so a generated recipe plays with no audio file
 * and no network. Each note schedules an oscillator with an attack→exponential
 * decay envelope and an optional frequency glissando.
 */
export function playRecipe(recipe: SoundRecipe, audioCtx: AudioContext): void {
  const now = audioCtx.currentTime;

  for (const voice of recipe.voices) {
    for (const note of voice.notes) {
      const startAt = now + Math.max(0, note.startAt);
      const endAt = startAt + Math.max(0.05, note.duration);
      const attack = Math.min(note.attack ?? 0.02, note.duration);
      const peak = Math.max(0.0001, Math.min(note.gain, 1));

      const oscillator = audioCtx.createOscillator();
      const gain = audioCtx.createGain();
      oscillator.type = voice.waveform;
      oscillator.frequency.setValueAtTime(note.freq, startAt);
      if (note.rampFreqTo !== undefined) {
        oscillator.frequency.linearRampToValueAtTime(note.rampFreqTo, endAt);
      }

      gain.gain.setValueAtTime(0.0001, startAt);
      gain.gain.linearRampToValueAtTime(peak, startAt + attack);
      gain.gain.exponentialRampToValueAtTime(0.0001, endAt);

      oscillator.connect(gain).connect(audioCtx.destination);
      oscillator.start(startAt);
      oscillator.stop(endAt);
    }
  }
}
