// ============================================================
// Extras - marquee ticker + flicker-on intro overlay
// ============================================================

// Retro scrolling marquee under the header --------------------------------
const MARQUEE_ITEMS = [
  'NOW BOOKING COMMISSIONS',
  'GLOW DROPS',
  'QUOTES WITHIN 72H',
  'ANIME · VINTAGE · FIDGET TOYS · STATUES',
  'PALM-SIZED TO 12 INCHES',
  'DESIGN · PRINT · CREATE',
];

function Marquee() {
  const row = (keyPrefix) =>
    MARQUEE_ITEMS.map((t, i) => {
      const accents = ['var(--cyan)', 'var(--magenta)', 'var(--sunset)', 'var(--vapor-purple)'];
      const c = `hsl(${accents[i % accents.length]})`;
      return (
        <span className="marquee-item" key={`${keyPrefix}-${i}`}>
          <span className="marquee-dot" style={{ background: c, boxShadow: `0 0 calc(8px * var(--glow,1)) ${c}, 0 0 calc(18px * var(--glow,1)) ${c}` }}></span>
          {t}
        </span>
      );
    });
  return (
    <div className="marquee" role="presentation" aria-hidden="true">
      <div className="marquee-track">
        {row('a')}
        {row('b')}
      </div>
    </div>
  );
}

// Tiny generated audio logo: beach wave -> tape warp -> synth pad ----------
function playFreshWaveIntroSound() {
  if (typeof window === 'undefined') return Promise.resolve(false);
  const AudioContextCtor = window.AudioContext || window.webkitAudioContext;
  if (!AudioContextCtor) return Promise.resolve(false);
  if (window.__fwIntroSoundActive) return Promise.resolve(true);

  const ctx = window.__fwAudioContext || new AudioContextCtor();
  window.__fwAudioContext = ctx;

  const schedule = () => {
    if (ctx.state === 'suspended') return false;
    window.__fwIntroSoundActive = true;
    window.setTimeout(() => { window.__fwIntroSoundActive = false; }, 2600);

    const now = ctx.currentTime + 0.025;
    const master = ctx.createGain();
    master.gain.setValueAtTime(0.0001, now);
    master.gain.linearRampToValueAtTime(0.24, now + 0.08);
    master.gain.exponentialRampToValueAtTime(0.0001, now + 2.35);
    master.connect(ctx.destination);

    const makeNoise = (duration, color = 0.985) => {
      const buffer = ctx.createBuffer(1, Math.ceil(ctx.sampleRate * duration), ctx.sampleRate);
      const data = buffer.getChannelData(0);
      let last = 0;
      for (let i = 0; i < data.length; i += 1) {
        const white = Math.random() * 2 - 1;
        last = (last * color) + (white * (1 - color));
        data[i] = last * 3.2;
      }
      const source = ctx.createBufferSource();
      source.buffer = buffer;
      return source;
    };

    // Faint CRT hiss underneath the whole boot.
    const staticSource = makeNoise(1.9, 0.52);
    const staticFilter = ctx.createBiquadFilter();
    const staticGain = ctx.createGain();
    staticFilter.type = 'highpass';
    staticFilter.frequency.setValueAtTime(1700, now);
    staticGain.gain.setValueAtTime(0.012, now);
    staticGain.gain.exponentialRampToValueAtTime(0.0001, now + 1.8);
    staticSource.connect(staticFilter);
    staticFilter.connect(staticGain);
    staticGain.connect(master);
    staticSource.start(now);
    staticSource.stop(now + 1.9);

    // Soft ocean wave that establishes "Fresh Wave" without becoming literal beach ambience.
    const wave = makeNoise(1.15, 0.992);
    const waveLow = ctx.createBiquadFilter();
    const waveHigh = ctx.createBiquadFilter();
    const waveGain = ctx.createGain();
    waveLow.type = 'lowpass';
    waveLow.frequency.setValueAtTime(360, now);
    waveLow.frequency.linearRampToValueAtTime(1380, now + 0.20);
    waveLow.frequency.exponentialRampToValueAtTime(460, now + 0.95);
    waveHigh.type = 'highpass';
    waveHigh.frequency.setValueAtTime(55, now);
    waveGain.gain.setValueAtTime(0.0001, now);
    waveGain.gain.linearRampToValueAtTime(0.18, now + 0.16);
    waveGain.gain.exponentialRampToValueAtTime(0.012, now + 0.95);
    wave.connect(waveLow);
    waveLow.connect(waveHigh);
    waveHigh.connect(waveGain);
    waveGain.connect(master);
    wave.start(now);
    wave.stop(now + 1.15);

    // Tape-warp bridge: the beach wave stretches into signal wave.
    const warp = ctx.createOscillator();
    const warpFilter = ctx.createBiquadFilter();
    const warpGain = ctx.createGain();
    warp.type = 'sawtooth';
    warp.frequency.setValueAtTime(112, now + 0.42);
    warp.frequency.exponentialRampToValueAtTime(52, now + 0.78);
    warp.frequency.linearRampToValueAtTime(84, now + 1.05);
    warpFilter.type = 'bandpass';
    warpFilter.frequency.setValueAtTime(720, now + 0.42);
    warpFilter.frequency.exponentialRampToValueAtTime(310, now + 1.05);
    warpFilter.Q.setValueAtTime(3.6, now);
    warpGain.gain.setValueAtTime(0.0001, now + 0.40);
    warpGain.gain.linearRampToValueAtTime(0.045, now + 0.62);
    warpGain.gain.exponentialRampToValueAtTime(0.0001, now + 1.16);
    warp.connect(warpFilter);
    warpFilter.connect(warpGain);
    warpGain.connect(master);
    warp.start(now + 0.40);
    warp.stop(now + 1.18);

    // VHS/PS1-ish synth pad: a place opening, not a song starting.
    const padGain = ctx.createGain();
    const padFilter = ctx.createBiquadFilter();
    padGain.gain.setValueAtTime(0.0001, now + 0.72);
    padGain.gain.linearRampToValueAtTime(0.075, now + 1.05);
    padGain.gain.exponentialRampToValueAtTime(0.0001, now + 2.30);
    padFilter.type = 'lowpass';
    padFilter.frequency.setValueAtTime(620, now + 0.72);
    padFilter.frequency.linearRampToValueAtTime(1180, now + 1.36);
    padFilter.Q.setValueAtTime(0.7, now);
    [146.83, 220.0, 293.66].forEach((freq, index) => {
      const osc = ctx.createOscillator();
      const voiceGain = ctx.createGain();
      osc.type = index === 1 ? 'triangle' : 'sine';
      osc.frequency.setValueAtTime(freq, now);
      osc.detune.setValueAtTime(index === 0 ? -7 : index === 1 ? 4 : 11, now);
      voiceGain.gain.setValueAtTime(index === 1 ? 0.55 : 0.38, now);
      osc.connect(voiceGain);
      voiceGain.connect(padFilter);
      osc.start(now + 0.72);
      osc.stop(now + 2.35);
    });
    padFilter.connect(padGain);
    padGain.connect(master);

    return true;
  };

  const resume = ctx.state === 'suspended' ? ctx.resume() : Promise.resolve();
  return resume.then(schedule).catch(() => false);
}

// Flicker-on intro overlay (once per browser session) ---------------------
function IntroOverlay() {
  const reduce = typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const seen = typeof sessionStorage !== 'undefined' && sessionStorage.getItem('fw-intro-seen') === '1';
  const [show, setShow] = useState(!seen && !reduce);
  const [done, setDone] = useState(false);

  useEffect(() => {
    if (!show) return;
    playFreshWaveIntroSound();
    const t1 = setTimeout(() => setDone(true), 2100);
    const t2 = setTimeout(() => { setShow(false); try { sessionStorage.setItem('fw-intro-seen', '1'); } catch (e) {} }, 2800);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [show]);

  const dismiss = () => {
    setDone(true);
    setTimeout(() => setShow(false), 500);
    try { sessionStorage.setItem('fw-intro-seen', '1'); } catch (e) {}
  };

  if (!show) return null;
  return (
    <div className={`intro-overlay ${done ? 'intro-done' : ''}`} onPointerDown={() => playFreshWaveIntroSound()} onClick={dismiss}>
      <LogoImage variant="full" alt="FreshWave Digital Studio" />
      <button className="intro-skip" onClick={dismiss}>Skip ▸</button>
    </div>
  );
}

Object.assign(window, { Marquee, IntroOverlay, playFreshWaveIntroSound });
