// Shared data + helpers for the Summer Bucket List worksheet
const { useState, useEffect, useRef, useMemo } = React;

// ---------- Vocabulary (A1) ----------
const VOCAB = [
  { id: 'beach',      word: 'beach',      phrase: 'go to the beach' },
  { id: 'icecream',   word: 'ice cream',  phrase: 'eat ice cream' },
  { id: 'swim',       word: 'swim',       phrase: 'swim in the sea' },
  { id: 'sandcastle', word: 'sandcastle', phrase: 'build a sandcastle' },
  { id: 'bike',       word: 'bike',       phrase: 'ride my bike' },
  { id: 'picnic',     word: 'picnic',     phrase: 'have a picnic' },
  { id: 'kite',       word: 'kite',       phrase: 'fly a kite' },
  { id: 'watermelon', word: 'watermelon', phrase: 'eat watermelon' },
];

function shuffleArr(arr) {
  const a = arr.slice();
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

// ---------- Sounds (WebAudio, no assets) ----------
const SFX = {
  enabled: true,
  ctx: null,
  ensure() {
    if (!this.ctx) {
      try { this.ctx = new (window.AudioContext || window.webkitAudioContext)(); } catch (e) {}
    }
    if (this.ctx && this.ctx.state === 'suspended') this.ctx.resume();
    return this.ctx;
  },
  tone(freq, start, dur, type, vol) {
    const ctx = this.ctx;
    const o = ctx.createOscillator();
    const g = ctx.createGain();
    o.type = type || 'sine';
    o.frequency.value = freq;
    g.gain.setValueAtTime(0.0001, ctx.currentTime + start);
    g.gain.linearRampToValueAtTime(vol || 0.18, ctx.currentTime + start + 0.02);
    g.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + start + dur);
    o.connect(g); g.connect(ctx.destination);
    o.start(ctx.currentTime + start);
    o.stop(ctx.currentTime + start + dur + 0.05);
  },
  click()   { if (!this.enabled || !this.ensure()) return; this.tone(620, 0, 0.08, 'sine', 0.1); },
  correct() { if (!this.enabled || !this.ensure()) return; this.tone(523, 0, 0.12); this.tone(784, 0.1, 0.18); },
  wrong()   { if (!this.enabled || !this.ensure()) return; this.tone(180, 0, 0.18, 'triangle', 0.12); },
  star()    { if (!this.enabled || !this.ensure()) return; this.tone(880, 0, 0.1); this.tone(1175, 0.08, 0.16, 'sine', 0.14); },
  win()     {
    if (!this.enabled || !this.ensure()) return;
    [523, 659, 784, 1047].forEach((f, i) => this.tone(f, i * 0.12, 0.22, 'sine', 0.16));
  },
};

// ---------- Speech (pronounce words) ----------
function speak(text) {
  if (!('speechSynthesis' in window)) return;
  window.speechSynthesis.cancel();
  const u = new SpeechSynthesisUtterance(text);
  u.lang = 'en-US';
  u.rate = 0.8;
  window.speechSynthesis.speak(u);
}

// ---------- Confetti ----------
window.__sblConfettiOn = true;
function burstConfetti(count) {
  if (!window.__sblConfettiOn) return;
  let host = document.getElementById('confetti-host');
  if (!host) {
    host = document.createElement('div');
    host.id = 'confetti-host';
    document.body.appendChild(host);
  }
  const colors = ['#FFC23E', '#3FA9E0', '#FF6F59', '#3BB273', '#F25C9B'];
  const n = count || 36;
  for (let i = 0; i < n; i++) {
    const p = document.createElement('div');
    p.className = 'confetti-piece';
    p.style.left = (5 + Math.random() * 90) + 'vw';
    p.style.background = colors[i % colors.length];
    p.style.animationDelay = (Math.random() * 0.4) + 's';
    p.style.animationDuration = (1.6 + Math.random() * 1.2) + 's';
    p.style.transform = 'rotate(' + Math.random() * 360 + 'deg)';
    if (i % 3 === 0) p.style.borderRadius = '50%';
    host.appendChild(p);
    setTimeout(() => p.remove(), 3200);
  }
}

// ---------- Photo placeholder (user will provide real photos) ----------
const VOCAB_IMAGES = {
  'beach': 'images/beach.png',
  'ice cream': 'images/icecream.png',
  'swim': 'images/swim.png',
  'sandcastle': 'images/sandcastle.png',
  'bike': 'images/bike.png',
  'picnic': 'images/picnic.png',
  'kite': 'images/kite.png',
  'watermelon': 'images/watermelon.png',
};
function PhotoSlot({ label, size, round }) {
  const src = VOCAB_IMAGES[label];
  if (src) {
    return (
      <img
        className="photo-img"
        src={src}
        alt={label}
        style={{
          width: size || '100%',
          height: size || 110,
          borderRadius: round ? '50%' : 14,
        }}
      />
    );
  }
  return (
    <div
      className="photo-slot"
      style={{
        width: size || '100%',
        height: size || 110,
        borderRadius: round ? '50%' : 14,
      }}
    >
      <span>photo:<br />{label}</span>
    </div>
  );
}

// ---------- Listen button ----------
function ListenBtn({ text, big }) {
  return (
    <button
      type="button"
      className={'listen-btn' + (big ? ' listen-big' : '')}
      onClick={(e) => { e.stopPropagation(); SFX.click(); speak(text); }}
      aria-label={'Listen: ' + text}
    >
      <span className="listen-glyph">&#9658;</span> Listen
    </button>
  );
}

// ---------- Star pop (floating +1 star feedback) ----------
function starPop(x, y) {
  const s = document.createElement('div');
  s.className = 'star-pop';
  s.textContent = '★ +1';
  s.style.left = x + 'px';
  s.style.top = y + 'px';
  document.body.appendChild(s);
  setTimeout(() => s.remove(), 900);
}

// ---------- Activity shell ----------
function ActivityShell({ stepNo, title, instructions, children }) {
  return (
    <div className="activity">
      <div className="activity-head">
        <div className="step-badge">{stepNo}</div>
        <div>
          <h2 className="activity-title">{title}</h2>
          <p className="activity-instructions">{instructions}</p>
        </div>
      </div>
      {children}
    </div>
  );
}

// ---------- Big friendly Next button ----------
function NextBtn({ onClick, label, disabled }) {
  return (
    <button
      type="button"
      className="btn btn-next"
      disabled={disabled}
      onClick={() => { SFX.click(); onClick(); }}
    >
      {label || 'Next'} <span className="next-arrow">&#8594;</span>
    </button>
  );
}

// ---------- Walking buddy (Lottie animation) ----------
function Mascot({ className, speed, style }) {
  const ref = useRef(null);
  useEffect(() => {
    if (!window.lottie || !ref.current) return;
    const anim = window.lottie.loadAnimation({
      container: ref.current,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      path: 'uploads/Totoro%20Walk.json',
    });
    if (speed) anim.setSpeed(speed);
    return () => anim.destroy();
  }, []);
  return <div className={className} style={style} ref={ref} aria-hidden="true"></div>;
}

Object.assign(window, {
  VOCAB, shuffleArr, SFX, speak, burstConfetti,
  PhotoSlot, ListenBtn, starPop, ActivityShell, NextBtn, Mascot,
});
