// audio.jsx — Web Audio synthesised sounds for Mahamon House
// All sounds generated programmatically. No file dependencies.
// DA-aligned: ultra-discrete, low volume, "quiet room" feel.

let _audioCtx = null;
let _soundEnabled = true;

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

function setSoundEnabled(enabled) {
  _soundEnabled = !!enabled;
}

// Single tone with fade-out
function tone(freq, duration = 0.1, volume = 0.06, type = 'sine', startOffset = 0) {
  if (!_soundEnabled) return;
  const ctx = getAudio();
  if (!ctx) return;
  try {
    const t0 = ctx.currentTime + startOffset;
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = type;
    osc.frequency.setValueAtTime(freq, t0);
    gain.gain.setValueAtTime(volume, t0);
    gain.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);
    osc.connect(gain);
    gain.connect(ctx.destination);
    osc.start(t0);
    osc.stop(t0 + duration + 0.02);
  } catch (e) {}
}

// Frequency sweep
function sweep(fromFreq, toFreq, duration = 0.2, volume = 0.06, type = 'sine') {
  if (!_soundEnabled) return;
  const ctx = getAudio();
  if (!ctx) return;
  try {
    const t0 = ctx.currentTime;
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = type;
    osc.frequency.setValueAtTime(fromFreq, t0);
    osc.frequency.exponentialRampToValueAtTime(Math.max(20, toFreq), t0 + duration);
    gain.gain.setValueAtTime(volume, t0);
    gain.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);
    osc.connect(gain);
    gain.connect(ctx.destination);
    osc.start(t0);
    osc.stop(t0 + duration + 0.02);
  } catch (e) {}
}

const sounds = {
  // Subtle UI feedback
  tick:    () => tone(1200, 0.03, 0.04, 'square'),
  click:   () => tone(640, 0.04, 0.05, 'sine'),

  // Wins — soft ascending
  win: () => {
    tone(659, 0.10, 0.05, 'sine', 0.00);  // E5
    tone(784, 0.18, 0.05, 'sine', 0.08);  // G5
  },
  bigWin: () => {
    tone(659, 0.10, 0.06, 'sine', 0.00);  // E5
    tone(784, 0.10, 0.06, 'sine', 0.08);  // G5
    tone(1047, 0.22, 0.06, 'sine', 0.16); // C6
  },

  // Loss — muted descending
  loss: () => {
    tone(220, 0.06, 0.05, 'triangle', 0.00);
    tone(165, 0.10, 0.05, 'triangle', 0.05);
  },

  // Push / neutral
  push: () => tone(440, 0.10, 0.04, 'sine'),

  // Card deal — short crisp flick
  cardDeal: () => tone(820, 0.022, 0.035, 'triangle'),

  // Slot reel stop — wooden tick, slightly lower than UI tick
  reelStop: () => tone(900, 0.04, 0.045, 'square'),

  // Dice tumble — short percussive
  diceRoll: () => tone(160, 0.025, 0.04, 'square'),

  // Number draw (Keno) — bright bell tip
  numberDraw: () => tone(1500, 0.025, 0.025, 'sine'),

  // Plinko peg hit — very subtle short tick
  pegHit: () => tone(1100, 0.018, 0.022, 'square'),

  // Crash / bust — descending sweep
  crash: () => sweep(440, 80, 0.30, 0.06, 'sawtooth'),

  // Tip received — warm chord
  tip: () => {
    tone(523, 0.20, 0.05, 'sine', 0.00);  // C5
    tone(659, 0.20, 0.05, 'sine', 0.00);  // E5
    tone(784, 0.30, 0.05, 'sine', 0.08);  // G5
  },

  // Roulette / spin starting — short ascending whisper
  spinStart: () => {
    tone(220, 0.05, 0.03, 'sine', 0.00);
    tone(330, 0.05, 0.03, 'sine', 0.04);
    tone(440, 0.07, 0.03, 'sine', 0.08);
  },

  // Rolling deceleration — ticks that slow over time (wheel/reel spinning down)
  // Returns a cancel function so the caller can abort if user navigates away.
  rollingDecel: (totalDuration = 6800, startFreq = 900, endFreq = 220, vol = 0.035) => {
    if (!_soundEnabled) return () => {};
    let cancelled = false;
    const start = performance.now();
    const tick = () => {
      if (cancelled) return;
      const elapsed = performance.now() - start;
      if (elapsed >= totalDuration) return;
      const progress = Math.min(1, elapsed / totalDuration);
      // Frequency drops over the spin
      const freq = startFreq - (startFreq - endFreq) * progress;
      tone(freq, 0.022, vol * (1 - progress * 0.4), 'square');
      // Tick interval grows from 70ms to 380ms (squared easing)
      const nextInterval = 70 + 310 * progress * progress;
      setTimeout(tick, nextInterval);
    };
    tick();
    return () => { cancelled = true; };
  },

  // Milestone tick — for Crash multiplier crossing 1.5x, 2x, 3x, etc.
  milestone: (level = 0) => {
    // Higher milestones = brighter, slightly louder
    const freq = 700 + Math.min(level, 6) * 80;
    tone(freq, 0.035, 0.04, 'sine');
  },

  // Crash rising tick — pitch grows with multiplier, sub-tick for ladder feel
  crashRise: (multiplier) => {
    const m = Math.max(1, multiplier);
    // Pitch climbs from 280 Hz at 1× toward ~900 Hz at 50×, capped
    const freq = Math.min(900, 280 + 90 * Math.log2(m));
    tone(freq, 0.022, 0.028, 'sine');
  },

  // Reveal a safe cell (Mines/Towers)
  reveal: () => tone(900, 0.04, 0.04, 'sine'),

  // Coin flip — woosh
  coinFlip: () => sweep(400, 700, 0.18, 0.04, 'triangle'),
};

Object.assign(window, { sounds, setSoundEnabled });
