// Bourdonnement + craquements d'un néon, entièrement synthétisés (Web Audio API).
// Aucun fichier audio à charger : deux oscillateurs légèrement désaccordés pour le
// bourdonnement électrique, un souffle de bruit filtré, et des craquements aléatoires
// (courtes rafales de bruit) qui imitent les micro-décharges d'un tube au néon.

export function startNeonBuzz(ctx: AudioContext): { stop: () => void } {
  const master = ctx.createGain()
  master.gain.value = 0.025 // volume réduit de 50 %
  master.connect(ctx.destination)

  // Bourdonnement électrique : deux oscillateurs proches en fréquence -> battement
  const hum1 = ctx.createOscillator()
  hum1.type = "sawtooth"
  hum1.frequency.value = 60
  const hum2 = ctx.createOscillator()
  hum2.type = "sawtooth"
  hum2.frequency.value = 120.5

  const humGain = ctx.createGain()
  humGain.gain.value = 0.35
  hum1.connect(humGain)
  hum2.connect(humGain)
  humGain.connect(master)

  // Souffle de fond (bruit blanc filtré en passe-bande)
  const noiseBuffer = ctx.createBuffer(1, ctx.sampleRate * 2, ctx.sampleRate)
  const data = noiseBuffer.getChannelData(0)
  for (let i = 0; i < data.length; i++) data[i] = Math.random() * 2 - 1

  const noise = ctx.createBufferSource()
  noise.buffer = noiseBuffer
  noise.loop = true

  const noiseFilter = ctx.createBiquadFilter()
  noiseFilter.type = "bandpass"
  noiseFilter.frequency.value = 3000
  noiseFilter.Q.value = 0.7

  const noiseGain = ctx.createGain()
  noiseGain.gain.value = 0.02
  noise.connect(noiseFilter)
  noiseFilter.connect(noiseGain)
  noiseGain.connect(master)

  hum1.start()
  hum2.start()
  noise.start()

  // Flicker : le tube perd et retrouve l'intensité par à-coups (bourdonnement ET
  // souffle ensemble), la signature d'un néon qui scintille plutôt qu'un simple
  // bourdonnement continu.
  let flickerTimeout: ReturnType<typeof setTimeout> | null = null
  function scheduleNextFlicker() {
    const delay = 900 + Math.random() * 3200
    flickerTimeout = setTimeout(() => {
      const now = ctx.currentTime
      const dip = 0.15 + Math.random() * 0.55 // intensité restante pendant le flicker
      const fall = 0.008 + Math.random() * 0.02
      const rise = 0.02 + Math.random() * 0.05

      humGain.gain.cancelScheduledValues(now)
      humGain.gain.setValueAtTime(humGain.gain.value, now)
      humGain.gain.linearRampToValueAtTime(0.35 * dip, now + fall)
      humGain.gain.linearRampToValueAtTime(0.35, now + fall + rise)

      // Parfois un second raté juste après, comme un tube qui hésite avant de se stabiliser
      if (Math.random() < 0.35) {
        const t2 = now + fall + rise + 0.05 + Math.random() * 0.08
        humGain.gain.linearRampToValueAtTime(0.35 * (0.2 + Math.random() * 0.4), t2 + fall)
        humGain.gain.linearRampToValueAtTime(0.35, t2 + fall + rise)
      }

      scheduleNextFlicker()
    }, delay)
  }
  scheduleNextFlicker()

  // Craquements aléatoires : courtes rafales de bruit filtré, à intervalles irréguliers
  let popTimeout: ReturnType<typeof setTimeout> | null = null
  function scheduleNextPop() {
    const delay = 60 + Math.random() * 500
    popTimeout = setTimeout(() => {
      const now = ctx.currentTime

      const popGain = ctx.createGain()
      popGain.gain.setValueAtTime(0, now)
      popGain.gain.linearRampToValueAtTime(0.15 + Math.random() * 0.25, now + 0.002)
      popGain.gain.exponentialRampToValueAtTime(0.001, now + 0.02 + Math.random() * 0.03)

      const popFilter = ctx.createBiquadFilter()
      popFilter.type = "highpass"
      popFilter.frequency.value = 1500 + Math.random() * 3000

      const popSource = ctx.createBufferSource()
      popSource.buffer = noiseBuffer
      popSource.connect(popFilter)
      popFilter.connect(popGain)
      popGain.connect(master)
      popSource.start(now)
      popSource.stop(now + 0.05)

      scheduleNextPop()
    }, delay)
  }
  scheduleNextPop()

  return {
    stop() {
      if (popTimeout) clearTimeout(popTimeout)
      if (flickerTimeout) clearTimeout(flickerTimeout)
      hum1.stop()
      hum2.stop()
      noise.stop()
      master.disconnect()
    },
  }
}
