const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();

const sounds: Record<string, AudioBuffer> = {};

async function loadSound(name: string): Promise<AudioBuffer> {
  const response = await fetch(`./sounds/${name}.ogg`);
  const arrayBuffer = await response.arrayBuffer();
  return audioCtx.decodeAudioData(arrayBuffer);
}

export async function initSounds() {
  const names = ['fireball', 'explosion', 'sword_hit1', 'teleport', 'damage', 'spiderwalking', 'spawn', 'gameover'];
  for (const name of names) {
    try {
      sounds[name] = await loadSound(name);
    } catch {
      console.warn(`Sound ${name} not found`);
    }
  }
}

export function resumeContext() {
  if (audioCtx.state === 'suspended') {
    audioCtx.resume();
  }
}

export function playSound(name: string, volume = 1) {
  const buffer = sounds[name];
  if (!buffer) return;
  if (audioCtx.state === 'suspended') return;
  const source = audioCtx.createBufferSource();
  source.buffer = buffer;
  const gain = audioCtx.createGain();
  gain.gain.value = volume;
  source.connect(gain);
  gain.connect(audioCtx.destination);
  source.start(0);
}

export function playLoopingSound(name: string, volume = 1): (() => void) | null {
  const buffer = sounds[name];
  if (!buffer) return null;
  if (audioCtx.state === 'suspended') return null;
  const source = audioCtx.createBufferSource();
  source.buffer = buffer;
  source.loop = true;
  const gain = audioCtx.createGain();
  gain.gain.value = volume;
  source.connect(gain);
  gain.connect(audioCtx.destination);
  source.start(0);
  return () => {
    try {
      source.stop();
    } catch {
      // already stopped
    }
    source.disconnect();
  };
}
