// ============ KID-FRIENDLY "WATCH & TAP" ============
// No words. A soft, friendly icon sails left <-> right along gentle arcs for a
// child to follow with their eyes. It quietly CHANGES into a new icon every few
// seconds — the moment it changes, tap anywhere. Each good tap adds to a score
// that is kept forever (saved on the device).

const { useState, useRef, useEffect, useCallback } = React;

// Clean, clear pastel palette — true soft hues, calm but not dusty
const friends = [
  { name: 'star',           color: '#f5cf57' },
  { name: 'heart',          color: '#f58a8a' },
  { name: 'rocket',         color: '#8e9bf0' },
  { name: 'fish',           color: '#5ec9b8' },
  { name: 'bird',           color: '#f5a85e' },
  { name: 'cat',            color: '#f0c265' },
  { name: 'dog',            color: '#d8a874' },
  { name: 'ice-cream-cone', color: '#f29ac4' },
  { name: 'candy',          color: '#ec85bf' },
  { name: 'gift',           color: '#f08585' },
  { name: 'apple',          color: '#82cf7a' },
  { name: 'sun',            color: '#f5d96b' },
  { name: 'cloud',          color: '#7ec2ec' },
  { name: 'flower-2',       color: '#ef8fc4' },
  { name: 'bug',            color: '#a8d472' },
  { name: 'smile',          color: '#f5d666' },
  { name: 'cake',           color: '#f2a3c4' },
  { name: 'car',            color: '#6fb8ec' },
  { name: 'plane',          color: '#9aa8f0' },
  { name: 'ghost',          color: '#b89ef0' },
  { name: 'sparkles',       color: '#f59ab0' },
  { name: 'gamepad-2',      color: '#66c8a8' },
];

const ICON_STROKE = '#55566e'; // soft dark slate — clear & calm on pastel fills

// lighten a #rrggbb colour toward white by t (0..1) -> opaque rgb() string
function lighten(hex, t) {
  const h = hex.replace('#', '');
  const m = (i) => { const c = parseInt(h.slice(i, i + 2), 16); return Math.round(c + (255 - c) * t); };
  return `rgb(${m(0)}, ${m(2)}, ${m(4)})`;
}

function lucideSvg(name, size, color) {
  const pascal = name.split('-').map(p => p.charAt(0).toUpperCase() + p.slice(1)).join('');
  if (typeof lucide !== 'undefined' && lucide.icons && lucide.icons[pascal]) {
    const svg = lucide.createElement(lucide.icons[pascal]);
    if (svg) {
      svg.setAttribute('width', size);
      svg.setAttribute('height', size);
      svg.setAttribute('stroke', color);
      svg.setAttribute('stroke-width', '2.4');
      return svg;
    }
  }
  return null;
}

// A soft little "pop" when a tap lands (Web Audio, no files needed)
let audioCtx = null;
function playPop() {
  try {
    if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    if (audioCtx.state === 'suspended') audioCtx.resume();
    const now = audioCtx.currentTime;
    const osc = audioCtx.createOscillator();
    const gain = audioCtx.createGain();
    osc.type = 'sine';
    osc.frequency.setValueAtTime(440, now);
    osc.frequency.exponentialRampToValueAtTime(620, now + 0.1);
    gain.gain.setValueAtTime(0.0001, now);
    gain.gain.exponentialRampToValueAtTime(0.06, now + 0.01);
    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.16);
    osc.connect(gain).connect(audioCtx.destination);
    osc.start(now);
    osc.stop(now + 0.18);
  } catch (e) { /* audio is a nice-to-have only */ }
}

function KidsGame() {
  const [iconIdx, setIconIdx] = useState(0);
  const [taps, setTaps] = useState(0); // taps this session
  const [badgePop, setBadgePop] = useState(false);
  const [showHint, setShowHint] = useState(true);
  const [sparks, setSparks] = useState([]);
  const [plusOnes, setPlusOnes] = useState([]);

  const stageRef = useRef(null);
  const friendRef = useRef(null);
  const iconHostRef = useRef(null);

  const motion = useRef({
    x: 0, dir: 1, p: 0,
    w: 0, h: 0, size: 120,
    xMin: 0, xMax: 0, baseY: 0,
    arc: 0.3, wave: 0.12, phase: 0,
    speed: 300, t: 0,
    nextChangeT: 2, changedAtT: -10,
  });
  const awaitingRef = useRef(false);   // true only while a fresh change is waiting for a tap
  const tapsRef = useRef(0);           // mirror of the session tap count
  const lastTapRef = useRef(0);
  const rafRef = useRef(null);
  const lastTsRef = useRef(0);
  const sparkId = useRef(0);

  const measure = useCallback(() => {
    const el = stageRef.current;
    if (!el) return;
    const m = motion.current;
    m.w = el.clientWidth;
    m.h = el.clientHeight;
    m.size = Math.max(80, Math.min(150, Math.min(m.w, m.h) * 0.22));
    m.xMin = m.size / 2 + 12;
    m.xMax = m.w - m.size / 2 - 12;
    m.baseY = m.h * 0.58;
    if (m.x === 0) m.x = m.xMin;
    if (friendRef.current) {
      friendRef.current.style.width = m.size + 'px';
      friendRef.current.style.height = m.size + 'px';
    }
  }, []);

  const randomizeArc = useCallback(() => {
    const m = motion.current;
    m.arc = 0.18 + Math.random() * 0.28;
    m.wave = Math.random() * 0.14;
    m.phase = Math.random() * Math.PI * 2;
  }, []);

  // swap to a new icon and open the "tap now" window
  const changeIcon = useCallback(() => {
    setIconIdx(prev => {
      let n;
      do { n = Math.floor(Math.random() * friends.length); } while (n === prev && friends.length > 1);
      return n;
    });
    awaitingRef.current = true;
    motion.current.changedAtT = motion.current.t;
    motion.current.nextChangeT = motion.current.t + 1.6 + Math.random() * 1.8;
  }, []);

  // paint current friend (soft fill, gentle shadow — no bloom)
  useEffect(() => {
    const host = iconHostRef.current;
    if (!host) return;
    host.innerHTML = '';
    const f = friends[iconIdx];
    const svg = lucideSvg(f.name, Math.round(motion.current.size * 0.5), ICON_STROKE);
    if (svg) host.appendChild(svg);
    if (friendRef.current) {
      friendRef.current.style.background = `radial-gradient(circle at 38% 32%, rgba(255,255,255,0.16), ${f.color} 64%)`;
      friendRef.current.style.boxShadow = `0 6px 16px rgba(0,0,0,0.22)`;
    }
    // wash the whole screen in a light, airy version of the current icon's
    // colour (lightened pastels stay clean, not muddy), easing on change
    if (stageRef.current) {
      stageRef.current.style.background =
        `radial-gradient(circle at 50% 32%, ${lighten(f.color, 0.62)} 0%, ${lighten(f.color, 0.40)} 100%)`;
    }
  }, [iconIdx]);

  // motion + auto-change loop
  useEffect(() => {
    measure();
    window.addEventListener('resize', measure);
    window.addEventListener('orientationchange', measure);
    randomizeArc();

    const tick = (ts) => {
      const m = motion.current;
      if (!lastTsRef.current) lastTsRef.current = ts;
      let dt = (ts - lastTsRef.current) / 1000;
      lastTsRef.current = ts;
      if (dt > 0.05) dt = 0.05;
      m.t += dt;

      m.speed = Math.min(520, 280 + tapsRef.current * 4);
      m.x += m.dir * m.speed * dt;
      if (m.x >= m.xMax) { m.x = m.xMax; m.dir = -1; randomizeArc(); }
      else if (m.x <= m.xMin) { m.x = m.xMin; m.dir = 1; randomizeArc(); }

      // time-based icon change (independent of bounces)
      if (m.t >= m.nextChangeT) changeIcon();

      const span = Math.max(1, m.xMax - m.xMin);
      m.p = (m.x - m.xMin) / span;
      const arcPx = m.arc * m.h;
      const wavePx = m.wave * m.h * 0.5;
      const y = m.baseY - Math.sin(m.p * Math.PI) * arcPx - Math.sin(m.p * Math.PI * 3 + m.phase) * wavePx;

      const tilt = Math.sin(m.t * 4) * 9 * m.dir;
      // gentle grow when it has just changed — a calm visual cue (no harsh flash)
      const sinceChange = m.t - m.changedAtT;
      const pop = sinceChange < 0.3 ? 1 + (1 - sinceChange / 0.3) * 0.16 : 1;

      if (friendRef.current) {
        friendRef.current.style.transform =
          `translate(${m.x - m.size / 2}px, ${y - m.size / 2}px) rotate(${tilt}deg) scale(${pop})`;
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener('resize', measure);
      window.removeEventListener('orientationchange', measure);
    };
  }, [measure, randomizeArc, changeIcon]);

  // tap handler — only counts while a fresh change is waiting
  const handlePointer = useCallback((e) => {
    const now = performance.now();
    if (now - lastTapRef.current < 250) return; // debounce double-fire
    lastTapRef.current = now;

    if (showHint) setShowHint(false);
    if (!awaitingRef.current) return;      // tapped when nothing changed -> no penalty, just ignore
    awaitingRef.current = false;

    const m = motion.current;
    const span = Math.max(1, m.xMax - m.xMin);
    const p = (m.x - m.xMin) / span;
    const arcPx = m.arc * m.h;
    const wavePx = m.wave * m.h * 0.5;
    const fy = m.baseY - Math.sin(p * Math.PI) * arcPx - Math.sin(p * Math.PI * 3 + m.phase) * wavePx;
    const f = friends[iconIdx];

    playPop();

    const newTaps = tapsRef.current + 1;
    tapsRef.current = newTaps;
    setTaps(newTaps);
    setBadgePop(true);
    setTimeout(() => setBadgePop(false), 300);

    // soft sparkle (no glow halo)
    const burst = [];
    const n = 8;
    for (let i = 0; i < n; i++) {
      const ang = (Math.PI * 2 * i) / n + Math.random() * 0.5;
      const dist = 50 + Math.random() * 55;
      burst.push({
        id: sparkId.current++,
        x: m.x, y: fy,
        dx: Math.cos(ang) * dist,
        dy: Math.sin(ang) * dist,
        size: 7 + Math.random() * 9,
        color: f.color,
      });
    }
    setSparks(prev => [...prev, ...burst]);
    const ids = burst.map(b => b.id);
    setTimeout(() => setSparks(prev => prev.filter(s => !ids.includes(s.id))), 700);

    const poId = sparkId.current++;
    setPlusOnes(prev => [...prev, { id: poId, x: m.x, y: fy }]);
    setTimeout(() => setPlusOnes(prev => prev.filter(p => p.id !== poId)), 900);
  }, [showHint, iconIdx]);

  const restart = useCallback((e) => {
    e.stopPropagation();
    tapsRef.current = 0;
    setTaps(0);
  }, []);

  const goHome = useCallback((e) => {
    e.stopPropagation();
    window.location.href = 'index.html';
  }, []);

  return (
    <div className="kids-stage" onPointerDown={handlePointer} ref={stageRef}>
      {/* taps this session */}
      <div className={`score-badge ${badgePop ? 'pop' : ''}`}>
        <StarIcon />
        <span className="num">{taps}</span>
      </div>

      <button className="corner-btn home" onPointerDown={goHome} aria-label="home"><HomeIcon /></button>
      <button className="corner-btn restart" onPointerDown={restart} aria-label="restart"><RestartIcon /></button>

      <div className="friend" ref={friendRef}>
        <span ref={iconHostRef} style={{ display: 'inline-flex' }} />
      </div>

      {sparks.map(s => (
        <div key={s.id} className="spark" style={{
          left: s.x + 'px', top: s.y + 'px',
          width: s.size + 'px', height: s.size + 'px',
          background: s.color,
          '--dx': `${s.dx}px`, '--dy': `${s.dy}px`,
        }} />
      ))}

      {plusOnes.map(p => (
        <div key={p.id} className="plus-one" style={{ left: p.x + 'px', top: p.y + 'px' }}>+1</div>
      ))}

      {showHint && (
        <div className="start-hint">
          <span className="pointer">👆</span>
          <HandTapIcon />
        </div>
      )}
    </div>
  );
}

// ---- small inline icons (rendered once) ----
function makeStaticIcon(name, size, color, strokeWidth) {
  return function StaticIcon() {
    const ref = useRef(null);
    useEffect(() => {
      if (!ref.current) return;
      ref.current.innerHTML = '';
      const svg = lucideSvg(name, size, color);
      if (svg) { if (strokeWidth) svg.setAttribute('stroke-width', strokeWidth); ref.current.appendChild(svg); }
    }, []);
    return <span ref={ref} style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }} />;
  };
}
const StarIcon = makeStaticIcon('star', 26, '#caa23a', '2.4');
const HomeIcon = makeStaticIcon('home', 26, '#4a4b63', '2.4');
const RestartIcon = makeStaticIcon('rotate-ccw', 26, '#4a4b63', '2.4');
const HandTapIcon = makeStaticIcon('hand', 34, 'rgba(74,75,99,0.85)', '2.4');

ReactDOM.createRoot(document.getElementById('root')).render(<KidsGame />);
