// Aumixo — Trilha cinematográfica épica/corporate
// Style: Apple/Tesla reveal — string section synth + sub drone + riser swell + cinematic impact
// 13s total, key C minor, 80 BPM-ish

function buildAumixoSoundtrack(ctx) {
  // ─── MASTER CHAIN ────────────────────────────────────────
  const master = ctx.createGain();
  master.gain.value = 0;
  const compressor = ctx.createDynamicsCompressor();
  compressor.threshold.value = -16;
  compressor.knee.value = 14;
  compressor.ratio.value = 5;
  compressor.attack.value = 0.005;
  compressor.release.value = 0.2;
  master.connect(compressor).connect(ctx.destination);

  master.gain.setValueAtTime(0, 0);
  master.gain.linearRampToValueAtTime(0.9, 0.8);
  master.gain.setValueAtTime(0.9, 11.5);
  master.gain.linearRampToValueAtTime(0, 12.8);

  // ─── REVERB BUS (algorithmic via convolver-like delay network) ──
  const fxBus = ctx.createGain();
  fxBus.gain.value = 1;
  fxBus.connect(master);

  // Multi-tap delay for cinematic space
  const delays = [0.07, 0.13, 0.23, 0.31, 0.43].map((t) => {
    const d = ctx.createDelay(2);
    d.delayTime.value = t;
    const g = ctx.createGain();
    g.gain.value = 0.18;
    fxBus.connect(d).connect(g).connect(master);
    return { d, g };
  });

  // Long tail
  const longDelay = ctx.createDelay(2);
  longDelay.delayTime.value = 0.6;
  const longFb = ctx.createGain();
  longFb.gain.value = 0.4;
  const longWet = ctx.createGain();
  longWet.gain.value = 0.22;
  fxBus.connect(longDelay);
  longDelay.connect(longFb).connect(longDelay);
  longDelay.connect(longWet).connect(master);

  // ─── 1. SUB DRONE — C1, low, throughout (cinematic foundation) ──
  {
    const osc1 = ctx.createOscillator();
    osc1.type = 'sine';
    osc1.frequency.value = 32.7; // C1
    const osc2 = ctx.createOscillator();
    osc2.type = 'triangle';
    osc2.frequency.value = 65.41; // C2
    osc2.detune.value = -7;
    const g = ctx.createGain();
    g.gain.setValueAtTime(0, 0);
    g.gain.linearRampToValueAtTime(0.35, 2.5);
    g.gain.setValueAtTime(0.35, 8.0);
    g.gain.linearRampToValueAtTime(0.5, 9.0); // surge at impact
    g.gain.linearRampToValueAtTime(0.25, 10.5);
    g.gain.linearRampToValueAtTime(0, 12.5);

    // Slow LFO for breathing
    const lfo = ctx.createOscillator();
    lfo.frequency.value = 0.3;
    const lfoGain = ctx.createGain();
    lfoGain.gain.value = 0.08;
    lfo.connect(lfoGain).connect(g.gain);

    osc1.connect(g).connect(master);
    osc2.connect(g);
    osc1.start(0); osc2.start(0); lfo.start(0);
    osc1.stop(13); osc2.stop(13); lfo.stop(13);
  }

  // ─── 2. STRING SECTION — sustained Cm chord (ensemble) ──
  // Detuned oscillator stack per voice for "ensemble" feel
  // Voicing: C3, Eb3, G3, C4, Eb4, G4
  const stringNotes = [
    { f: 130.81, t: 1.5, dur: 11.0, gain: 0.07 }, // C3
    { f: 155.56, t: 1.5, dur: 11.0, gain: 0.07 }, // Eb3
    { f: 196.00, t: 1.5, dur: 11.0, gain: 0.07 }, // G3
    { f: 261.63, t: 3.0, dur: 9.5,  gain: 0.05 }, // C4 (joins later)
    { f: 311.13, t: 3.0, dur: 9.5,  gain: 0.05 }, // Eb4
    { f: 392.00, t: 6.0, dur: 6.5,  gain: 0.04 }, // G4 (top voice — manifesto)
  ];
  stringNotes.forEach(({ f, t, dur, gain }) => {
    // Ensemble: 3 detuned sawtooth voices through lowpass (string-like)
    [-12, 0, 11].forEach((cents) => {
      const osc = ctx.createOscillator();
      osc.type = 'sawtooth';
      osc.frequency.value = f;
      osc.detune.value = cents;

      // Slight vibrato
      const vibrato = ctx.createOscillator();
      vibrato.frequency.value = 4.5 + Math.random() * 0.5;
      const vibGain = ctx.createGain();
      vibGain.gain.value = f * 0.003;
      vibrato.connect(vibGain).connect(osc.frequency);

      const filter = ctx.createBiquadFilter();
      filter.type = 'lowpass';
      filter.frequency.setValueAtTime(800, t);
      filter.frequency.linearRampToValueAtTime(2200, t + dur * 0.4);
      filter.frequency.linearRampToValueAtTime(1400, t + dur);
      filter.Q.value = 1.5;

      const g = ctx.createGain();
      const peak = gain / 3;
      g.gain.setValueAtTime(0, t);
      g.gain.linearRampToValueAtTime(peak, t + 1.2); // slow attack = strings
      g.gain.setValueAtTime(peak, t + dur - 1.5);
      g.gain.linearRampToValueAtTime(0, t + dur);

      osc.connect(filter).connect(g).connect(fxBus);
      osc.start(t); vibrato.start(t);
      osc.stop(t + dur + 0.1); vibrato.stop(t + dur + 0.1);
    });
  });

  // ─── 3. CINEMATIC TICKS — sparse during build (0.5–2.5s) ──
  const tickTimes = [0.6, 1.0, 1.4, 1.8, 2.2];
  tickTimes.forEach((t, i) => {
    // Wood tick: short noise burst + sine
    const bufferSize = ctx.sampleRate * 0.05;
    const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
    const data = noiseBuffer.getChannelData(0);
    for (let j = 0; j < bufferSize; j++) data[j] = (Math.random() * 2 - 1) * Math.exp(-j / (bufferSize * 0.3));
    const noise = ctx.createBufferSource();
    noise.buffer = noiseBuffer;
    const noiseFilter = ctx.createBiquadFilter();
    noiseFilter.type = 'highpass';
    noiseFilter.frequency.value = 2000;
    const noiseGain = ctx.createGain();
    noiseGain.gain.value = 0.04;
    noise.connect(noiseFilter).connect(noiseGain).connect(master);
    noise.start(t);

    // Subtle pitched tick
    const osc = ctx.createOscillator();
    osc.type = 'triangle';
    osc.frequency.value = 800 + i * 60;
    const g = ctx.createGain();
    g.gain.setValueAtTime(0, t);
    g.gain.linearRampToValueAtTime(0.03, t + 0.003);
    g.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
    osc.connect(g).connect(master);
    osc.start(t); osc.stop(t + 0.06);
  });

  // ─── 4. BIG RISER — building tension (5.5–9s) ──
  {
    // Rising filtered noise
    const bufferSize = ctx.sampleRate * 4;
    const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
    const data = noiseBuffer.getChannelData(0);
    for (let i = 0; i < bufferSize; i++) data[i] = Math.random() * 2 - 1;
    const noise = ctx.createBufferSource();
    noise.buffer = noiseBuffer;
    const filter = ctx.createBiquadFilter();
    filter.type = 'bandpass';
    filter.Q.value = 4;
    filter.frequency.setValueAtTime(200, 5.5);
    filter.frequency.exponentialRampToValueAtTime(8000, 9.0);
    const g = ctx.createGain();
    g.gain.setValueAtTime(0, 5.5);
    g.gain.linearRampToValueAtTime(0.05, 7.0);
    g.gain.linearRampToValueAtTime(0.18, 8.95);
    g.gain.exponentialRampToValueAtTime(0.001, 9.4);
    noise.connect(filter).connect(g).connect(fxBus);
    noise.start(5.5); noise.stop(9.5);

    // Pitched riser (sub-octave sweep)
    const osc = ctx.createOscillator();
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(60, 5.5);
    osc.frequency.exponentialRampToValueAtTime(800, 9.0);
    const oscFilter = ctx.createBiquadFilter();
    oscFilter.type = 'lowpass';
    oscFilter.Q.value = 8;
    oscFilter.frequency.setValueAtTime(150, 5.5);
    oscFilter.frequency.exponentialRampToValueAtTime(2500, 9.0);
    const og = ctx.createGain();
    og.gain.setValueAtTime(0, 5.5);
    og.gain.linearRampToValueAtTime(0.04, 7.0);
    og.gain.linearRampToValueAtTime(0.12, 8.95);
    og.gain.exponentialRampToValueAtTime(0.001, 9.3);
    osc.connect(oscFilter).connect(og).connect(fxBus);
    osc.start(5.5); osc.stop(9.4);
  }

  // ─── 5. CINEMATIC IMPACT — at lockup (9s) ──
  // Combination: sub boom + transient + reverb tail
  {
    const t = 9.0;
    // Sub boom (low sine drop)
    const sub = ctx.createOscillator();
    sub.type = 'sine';
    sub.frequency.setValueAtTime(120, t);
    sub.frequency.exponentialRampToValueAtTime(35, t + 0.5);
    const subG = ctx.createGain();
    subG.gain.setValueAtTime(0, t);
    subG.gain.linearRampToValueAtTime(0.55, t + 0.01);
    subG.gain.exponentialRampToValueAtTime(0.001, t + 1.5);
    sub.connect(subG).connect(master);
    sub.start(t); sub.stop(t + 1.6);

    // Transient (noise burst with reverb)
    const bufferSize = ctx.sampleRate * 0.25;
    const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
    const data = noiseBuffer.getChannelData(0);
    for (let i = 0; i < bufferSize; i++) {
      data[i] = (Math.random() * 2 - 1) * Math.exp(-i / (bufferSize * 0.15));
    }
    const noise = ctx.createBufferSource();
    noise.buffer = noiseBuffer;
    const noiseFilter = ctx.createBiquadFilter();
    noiseFilter.type = 'lowpass';
    noiseFilter.frequency.value = 4000;
    const noiseG = ctx.createGain();
    noiseG.gain.value = 0.25;
    noise.connect(noiseFilter).connect(noiseG).connect(fxBus);
    noise.start(t);

    // Mid impact (filtered saw stab)
    const stab = ctx.createOscillator();
    stab.type = 'sawtooth';
    stab.frequency.value = 65.41; // C2
    const stabFilter = ctx.createBiquadFilter();
    stabFilter.type = 'lowpass';
    stabFilter.Q.value = 6;
    stabFilter.frequency.setValueAtTime(3000, t);
    stabFilter.frequency.exponentialRampToValueAtTime(200, t + 0.4);
    const stabG = ctx.createGain();
    stabG.gain.setValueAtTime(0, t);
    stabG.gain.linearRampToValueAtTime(0.18, t + 0.02);
    stabG.gain.exponentialRampToValueAtTime(0.001, t + 0.6);
    stab.connect(stabFilter).connect(stabG).connect(fxBus);
    stab.start(t); stab.stop(t + 0.7);
  }

  // ─── 6. RESOLUTION CHORD — final hold (9.2–12.5s) ──
  // Cm9 (warm cinematic resolution): C, Eb, G, Bb, D
  const resolutionNotes = [
    { f: 130.81, gain: 0.06 }, // C3
    { f: 155.56, gain: 0.05 }, // Eb3
    { f: 196.00, gain: 0.05 }, // G3
    { f: 233.08, gain: 0.04 }, // Bb3
    { f: 293.66, gain: 0.04 }, // D4
    { f: 523.25, gain: 0.03 }, // C5 (top sparkle)
  ];
  resolutionNotes.forEach(({ f, gain }) => {
    [-8, 0, 9].forEach((cents) => {
      const osc = ctx.createOscillator();
      osc.type = f > 400 ? 'sine' : 'sawtooth';
      osc.frequency.value = f;
      osc.detune.value = cents;

      const filter = ctx.createBiquadFilter();
      filter.type = 'lowpass';
      filter.frequency.value = f > 400 ? 6000 : 2200;
      filter.Q.value = 1;

      const g = ctx.createGain();
      const peak = gain / 3;
      g.gain.setValueAtTime(0, 9.0);
      g.gain.linearRampToValueAtTime(peak, 9.5);
      g.gain.setValueAtTime(peak, 11.5);
      g.gain.linearRampToValueAtTime(0, 12.8);

      osc.connect(filter).connect(g).connect(fxBus);
      osc.start(9.0); osc.stop(13);
    });
  });

  // ─── 7. SOFT CHIME SPARKLE — final (9.1s) ──
  const sparkleNotes = [1046.5, 1318.5, 1568.0]; // C6, E6, G6
  sparkleNotes.forEach((f, i) => {
    const t = 9.1 + i * 0.06;
    const osc = ctx.createOscillator();
    osc.type = 'sine';
    osc.frequency.value = f;
    const g = ctx.createGain();
    g.gain.setValueAtTime(0, t);
    g.gain.linearRampToValueAtTime(0.06, t + 0.02);
    g.gain.exponentialRampToValueAtTime(0.001, t + 3.0);
    osc.connect(g).connect(fxBus);
    osc.start(t); osc.stop(t + 3.1);
  });

  return master;
}

// ─── App wrapper: Stage + audio sync ───────────────────────
function App({ width = 1920, height = 1080 }) {
  const [audioOn, setAudioOn] = React.useState(false);
  const [muted, setMuted] = React.useState(false);
  const ctxRef = React.useRef(null);

  const startAudio = async () => {
    if (ctxRef.current) {
      try { await ctxRef.current.close(); } catch {}
      ctxRef.current = null;
    }
    const ctx = new (window.AudioContext || window.webkitAudioContext)();
    if (ctx.state === 'suspended') await ctx.resume();
    ctxRef.current = ctx;
    buildAumixoSoundtrack(ctx);
    setAudioOn(true);

    let lastT = 0;
    setInterval(() => {
      try {
        const persistKey = (window.__animPersistKey || 'animstage') + ':t';
        const t = parseFloat(localStorage.getItem(persistKey) || '0');
        if (t < lastT - 1) {
          try { ctxRef.current?.close(); } catch {}
          const c = new (window.AudioContext || window.webkitAudioContext)();
          ctxRef.current = c;
          buildAumixoSoundtrack(c);
        }
        lastT = t;
      } catch {}
    }, 200);
  };

  const toggleMute = () => {
    if (!ctxRef.current) return;
    if (ctxRef.current.state === 'running') {
      ctxRef.current.suspend();
      setMuted(true);
    } else {
      ctxRef.current.resume();
      setMuted(false);
    }
  };

  const SceneComponent = window.SceneFor ? window.SceneFor(width, height) : window.Scene;

  return (
    <>
      <Stage width={width} height={height} duration={13} background="#050b16" loop>
        <SceneComponent/>
      </Stage>

      <div style={{
        position:'fixed', top:20, right:20, zIndex:1000,
        display:'flex', gap:10, alignItems:'center',
        fontFamily:"'JetBrains Mono', monospace", fontSize:12,
        letterSpacing:'0.1em', textTransform:'uppercase'
      }}>
        {!audioOn ? (
          <button onClick={startAudio} style={btnStyle}>
            ▶ Ativar trilha
          </button>
        ) : (
          <button onClick={toggleMute} style={btnStyle}>
            {muted ? '🔇 Mute' : '🔊 Som ligado'}
          </button>
        )}
      </div>
    </>
  );
}

const btnStyle = {
  padding:'10px 18px',
  borderRadius:99,
  background:'rgba(59,130,246,0.15)',
  border:'1px solid rgba(59,130,246,0.5)',
  color:'#60a5fa',
  fontFamily:'inherit',
  fontSize:'inherit',
  letterSpacing:'inherit',
  textTransform:'inherit',
  cursor:'pointer',
  backdropFilter:'blur(8px)',
};

Object.assign(window, { App, buildAumixoSoundtrack });
