/**
 * VibeLoop – eigener Sound pro Geschenk (Web Audio API).
 */
const VibeLoopSounds = (function () {
  let ctx = null;

  function audio() {
    if (!ctx) {
      const AC = window.AudioContext || window.webkitAudioContext;
      if (!AC) return null;
      ctx = new AC();
    }
    if (ctx.state === 'suspended') ctx.resume().catch(() => {});
    return ctx;
  }

  function tone(ac, freq, start, dur, type, vol, detune) {
    const o = ac.createOscillator();
    const g = ac.createGain();
    o.type = type || 'sine';
    o.frequency.value = freq;
    if (detune) o.detune.value = detune;
    g.gain.setValueAtTime(0.0001, start);
    g.gain.exponentialRampToValueAtTime(vol || 0.2, start + 0.02);
    g.gain.exponentialRampToValueAtTime(0.0001, start + dur);
    o.connect(g);
    g.connect(ac.destination);
    o.start(start);
    o.stop(start + dur + 0.05);
  }

  function noiseBurst(ac, start, dur, vol) {
    const bufferSize = ac.sampleRate * dur;
    const buffer = ac.createBuffer(1, bufferSize, ac.sampleRate);
    const data = buffer.getChannelData(0);
    for (let i = 0; i < bufferSize; i++) data[i] = (Math.random() * 2 - 1) * (1 - i / bufferSize);
    const src = ac.createBufferSource();
    src.buffer = buffer;
    const g = ac.createGain();
    const f = ac.createBiquadFilter();
    f.type = 'bandpass';
    f.frequency.value = 1200;
    g.gain.setValueAtTime(vol || 0.15, start);
    g.gain.exponentialRampToValueAtTime(0.0001, start + dur);
    src.connect(f);
    f.connect(g);
    g.connect(ac.destination);
    src.start(start);
    src.stop(start + dur);
  }

  function sweep(ac, f0, f1, start, dur, vol) {
    const o = ac.createOscillator();
    const g = ac.createGain();
    o.type = 'sawtooth';
    o.frequency.setValueAtTime(f0, start);
    o.frequency.exponentialRampToValueAtTime(f1, start + dur);
    g.gain.setValueAtTime(0.0001, start);
    g.gain.exponentialRampToValueAtTime(vol || 0.12, start + 0.03);
    g.gain.exponentialRampToValueAtTime(0.0001, start + dur);
    o.connect(g);
    g.connect(ac.destination);
    o.start(start);
    o.stop(start + dur + 0.05);
  }

  const PLAYERS = {
    rose(ac, t) {
      tone(ac, 523, t, 0.35, 'sine', 0.22);
      tone(ac, 659, t + 0.08, 0.4, 'triangle', 0.15);
    },
    heart(ac, t) {
      tone(ac, 392, t, 0.5, 'sine', 0.2);
      tone(ac, 494, t + 0.1, 0.55, 'sine', 0.18);
      tone(ac, 587, t + 0.2, 0.6, 'triangle', 0.14);
    },
    clap(ac, t) {
      noiseBurst(ac, t, 0.08, 0.25);
      noiseBurst(ac, t + 0.1, 0.06, 0.2);
      noiseBurst(ac, t + 0.18, 0.05, 0.18);
    },
    fire(ac, t) {
      sweep(ac, 200, 900, t, 0.25, 0.14);
      tone(ac, 880, t + 0.15, 0.2, 'square', 0.08);
    },
    star(ac, t) {
      tone(ac, 988, t, 0.15, 'sine', 0.2);
      tone(ac, 1319, t + 0.06, 0.2, 'sine', 0.16);
      tone(ac, 1568, t + 0.12, 0.25, 'triangle', 0.12);
    },
    diamond(ac, t) {
      tone(ac, 1175, t, 0.5, 'sine', 0.22);
      tone(ac, 1568, t + 0.05, 0.45, 'triangle', 0.16);
      tone(ac, 2093, t + 0.12, 0.35, 'sine', 0.1);
    },
    rocket(ac, t) {
      sweep(ac, 120, 1800, t, 0.45, 0.13);
      tone(ac, 440, t + 0.35, 0.3, 'square', 0.1);
    },
    crown(ac, t) {
      tone(ac, 523, t, 0.25, 'square', 0.12);
      tone(ac, 659, t + 0.12, 0.25, 'square', 0.12);
      tone(ac, 784, t + 0.24, 0.25, 'square', 0.12);
      tone(ac, 1047, t + 0.36, 0.5, 'sine', 0.18);
    },
  };

  function play(giftType) {
    if (localStorage.getItem('cp_mute_gifts') === '1') return;
    const ac = audio();
    if (!ac) return;
    const fn = PLAYERS[giftType] || PLAYERS.rose;
    const t = ac.currentTime + 0.01;
    try {
      fn(ac, t);
    } catch (e) {}
  }

  function setMuted(muted) {
    if (muted) localStorage.setItem('cp_mute_gifts', '1');
    else localStorage.removeItem('cp_mute_gifts');
  }

  function isMuted() {
    return localStorage.getItem('cp_mute_gifts') === '1';
  }

  return { play, setMuted, isMuted };
})();

if (typeof window !== 'undefined') window.VibeLoopSounds = VibeLoopSounds;
