// Core: theme, mascot, sounds, shared UI primitives.
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ── Sound engine (WebAudio) ──────────────────────────────────────────
const SFX = (() => {
  let ctx = null;
  let muted = false;
  const ensure = () => {
    if (!ctx) {
      try { ctx = new (window.AudioContext || window.webkitAudioContext)(); } catch (_) {}
    }
    if (ctx && ctx.state === 'suspended') ctx.resume();
    return ctx;
  };
  const tone = (freq, dur = 0.12, type = 'square', vol = 0.08, slide) => {
    if (muted) return;
    const c = ensure();
    if (!c) return;
    const t0 = c.currentTime;
    const o = c.createOscillator();
    const g = c.createGain();
    o.type = type;
    o.frequency.setValueAtTime(freq, t0);
    if (slide) o.frequency.exponentialRampToValueAtTime(slide, t0 + dur);
    g.gain.setValueAtTime(vol, t0);
    g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
    o.connect(g).connect(c.destination);
    o.start(t0); o.stop(t0 + dur);
  };
  return {
    setMuted(v) { muted = v; },
    isMuted() { return muted; },
    click()    { tone(620, 0.05, 'square', 0.06); },
    hover()    { tone(880, 0.04, 'triangle', 0.03); },
    select()   { tone(440, 0.07, 'square', 0.07, 880); },
    correct()  { tone(660, 0.09, 'square', 0.09, 990); setTimeout(() => tone(990, 0.12, 'square', 0.09, 1320), 80); },
    wrong()    { tone(220, 0.18, 'sawtooth', 0.09, 110); },
    win()      { [523, 659, 784, 1047].forEach((f, i) => setTimeout(() => tone(f, 0.18, 'square', 0.1), i * 110)); },
    lose()     { [330, 247, 175].forEach((f, i) => setTimeout(() => tone(f, 0.22, 'sawtooth', 0.09), i * 140)); },
    type()     { tone(1200 + Math.random() * 400, 0.025, 'square', 0.025); },
    tick()     { tone(1500, 0.02, 'square', 0.04); },
    powerOn()  { tone(120, 0.4, 'sawtooth', 0.12, 1200); },
    powerOff() { tone(1200, 0.3, 'sawtooth', 0.12, 80); },
    boot()     { [262, 392, 523, 784].forEach((f, i) => setTimeout(() => tone(f, 0.1, 'square', 0.08), i * 70)); },
  };
})();
window.SFX = SFX;

// ── High score store ─────────────────────────────────────────────────
const SCORE_KEY = 'cyber-arcade-scores-v1';
function loadScores() {
  try { return JSON.parse(localStorage.getItem(SCORE_KEY) || '{}'); } catch { return {}; }
}
function saveScore(gameId, score) {
  const s = loadScores();
  if (!s[gameId] || score > s[gameId]) {
    s[gameId] = score;
    localStorage.setItem(SCORE_KEY, JSON.stringify(s));
  }
  return s;
}
function clearScores() { localStorage.removeItem(SCORE_KEY); }
window.loadScores = loadScores;
window.saveScore = saveScore;
window.clearScores = clearScores;

// ── Pixel mascot SCANNER (rendered with CSS box-shadow grid) ─────────
// Grid is 14×14, each cell 6px → 84×84 sprite. Scaled via transform.
const SCANNER_FRAMES = {
  // legend: '.' transparent, 'C' cyan, 'D' dark cyan, 'W' white, 'B' black, 'P' pink (cheek), 'Y' yellow
  happy: [
    '...CCCCCC....',
    '..CDDDDDDC...',
    '.CDWWWWWWDC..',
    '.CDWBWWWBWDC.',
    'CDWWBWWBWWDC.',
    'CDWWWWWWWWDC.',
    'CDWPWWWWPWDC.',
    'CDWWBBBBWWDC.',
    '.CDWWWWWWDC..',
    '.CDDDDDDDC...',
    '..CCCCCDDDC..',
    '.....DDDDC...',
    '......DDDC...',
    '.......DDC...'
  ],
  worried: [
    '...CCCCCC....',
    '..CDDDDDDC...',
    '.CDWWWWWWDC..',
    '.CDWWBWBWWDC.',
    'CDWWBWWBWWDC.',
    'CDWWWWWWWWDC.',
    'CDWWWBBWWWDC.',
    'CDWWBWWBWWDC.',
    '.CDWWWWWWDC..',
    '.CDDDDDDDC...',
    '..CCCCCDDDC..',
    '.....DDDDC...',
    '......DDDC...',
    '.......DDC...'
  ],
  alert: [
    '...CCCCCC....',
    '..CDDDDDDC...',
    '.CDWWWWWWDC..',
    '.CDWYBYWBYDC.',
    'CDWYBWWBYWDC.',
    'CDWWWWWWWWDC.',
    'CDWWWWWWWWDC.',
    'CDWWBBBBWWDC.',
    '.CDWWBBWWDC..',
    '.CDDDDDDDC...',
    '..CCCCCDDDC..',
    '.....DDDDC...',
    '......DDDC...',
    '.......DDC...'
  ],
  cheering: [
    'Y..CCCCCC..Y.',
    '.YCDDDDDDCY..',
    '.CDWWWWWWDC..',
    'YCDWBWWWBWDCY',
    'CDWWBWWBWWDC.',
    'CDWWWWWWWWDC.',
    'CDWWBBBBWWDC.',
    'CDWBWWWWBWDC.',
    '.CDWBBBBWWDC.',
    '.CDDDDDDDC...',
    '..CCCCCDDDC..',
    '.....DDDDC...',
    '......DDDC...',
    '.......DDC...'
  ],
  facepalm: [
    '...CCCCCC....',
    '..CDDDDDDC...',
    '.CDWWWWWWDC..',
    '.CDWWWWWWWDC.',
    'CDWWWWWWWWDC.',
    'CDWBBBBBBWDC.',
    'CDWWWWWWWWDC.',
    'CDWWBWWBWWDC.',
    '.CDWWBBBBWDC.',
    '.CDDDDDDDC...',
    '..CCCCCDDDC..',
    '.....DDDDC...',
    '......DDDC...',
    '.......DDC...'
  ],
};
const PIX_COLORS = { C: '#34e6ff', D: '#0a8aa3', W: '#eafcff', B: '#0a141a', P: '#ff6fb6', Y: '#ffd84d' };

function Scanner({ mood = 'happy', size = 84, animate = true, style = {} }) {
  const frame = SCANNER_FRAMES[mood] || SCANNER_FRAMES.happy;
  const cols = frame[0].length, rows = frame.length;
  const cell = size / Math.max(cols, rows);
  const rects = [];
  frame.forEach((row, y) => {
    [...row].forEach((ch, x) => {
      if (PIX_COLORS[ch]) {
        rects.push(<rect key={`${x}-${y}`} x={x * cell} y={y * cell} width={cell + 0.5} height={cell + 0.5} fill={PIX_COLORS[ch]} />);
      }
    });
  });
  return (
    <svg
      width={size} height={size} viewBox={`0 0 ${size} ${size}`}
      className={animate ? 'scanner-bob' : ''}
      style={{ filter: 'drop-shadow(0 0 8px rgba(52,230,255,0.55))', display:'inline-block', ...style }}
    >{rects}</svg>
  );
}
window.Scanner = Scanner;

// ── Speech bubble for mascot ────────────────────────────────────────
function MascotLine({ mood = 'happy', children, size = 72 }) {
  return (
    <div style={{display:'flex', alignItems:'center', gap:18}}>
      <Scanner mood={mood} size={size} />
      {children && (
        <div className="mascot-bubble">{children}</div>
      )}
    </div>
  );
}
window.MascotLine = MascotLine;

// ── Reusable arcade button ───────────────────────────────────────────
function ArcadeButton({ children, onClick, color = '#34e6ff', textColor = '#04101a', disabled, size = 'md', style = {}, type='button' }) {
  const sizes = {
    sm: { padding: '10px 18px', fontSize: 14 },
    md: { padding: '16px 28px', fontSize: 16 },
    lg: { padding: '22px 40px', fontSize: 22 },
  };
  return (
    <button
      type={type}
      onClick={(e) => { if (disabled) return; SFX.click(); onClick && onClick(e); }}
      onMouseEnter={() => !disabled && SFX.hover()}
      disabled={disabled}
      className="arc-btn"
      style={{
        ...sizes[size],
        background: disabled ? '#1a2530' : color,
        color: disabled ? '#3a4a55' : textColor,
        boxShadow: disabled
          ? 'inset 0 -4px 0 #0e1620, 0 4px 0 #0e1620'
          : `inset 0 -6px 0 rgba(0,0,0,0.32), 0 6px 0 rgba(0,0,0,0.45), 0 0 18px ${color}66`,
        ...style,
      }}
    >
      {children}
    </button>
  );
}
window.ArcadeButton = ArcadeButton;

// ── Pixel icons rendered same way as scanner ────────────────────────
const ICON_FRAMES = {
  glass: [
    '..CCCCCC..',
    '.CWWWWWWC.',
    'CWWBBBBWWC',
    'CWBWWWWBWC',
    'CWBWWWWBWC',
    'CWWBBBBWWC',
    '.CWWWWCC..',
    '..CCCC.CC.',
    '........CC',
    '.........C',
  ],
  lock: [
    '...CCCC...',
    '..CWWWWC..',
    '.CW....WC.',
    'CW......WC',
    'CCCCCCCCCC',
    'CWWWWWWWWC',
    'CWW.BB..WC',
    'CWW.BB..WC',
    'CWWWWWWWWC',
    'CCCCCCCCCC',
  ],
  chat: [
    'CCCCCCCC..',
    'CWWWWWWC..',
    'CW.B.B.C..',
    'CWWWWWWC..',
    'CW.BB..C..',
    'CWWWWWWC..',
    'CCCCCCCC..',
    '.CC.......',
    '..C.......',
    '..........',
  ],
  shield: [
    '..CCCCCC..',
    '.CWWWWWWC.',
    'CWWWWWWWWC',
    'CWWBWWBWWC',
    'CWWBWWBWWC',
    'CWWWBBWWWC',
    'CWWWWWWWWC',
    '.CWWWWWWC.',
    '..CWWWWC..',
    '...CCCC...',
  ],
  link: [
    'CCCC......',
    'CWWC......',
    'CWWCCCC...',
    'CCCWWWC...',
    '..CWWWCCCC',
    '...CCCWWWC',
    '......CWWC',
    '......CCCC',
    '..........',
    '..........',
  ],
  phone: [
    '.CCCCCC...',
    '.CWWWWWC..',
    '.CWBBWWC..',
    '.CWWWWWC..',
    '.CWWWWWC..',
    '.CWWWWWC..',
    '.CWWWWWC..',
    '.CWWBWWC..',
    '.CCCCCCC..',
    '..........',
  ],
};
function PixIcon({ name, size = 60, color = '#34e6ff', style = {} }) {
  const frame = ICON_FRAMES[name];
  if (!frame) return null;
  const cols = frame[0].length, rows = frame.length;
  const cell = size / Math.max(cols, rows);
  const palette = { C: color, W: '#eafcff', B: '#04101a' };
  const rects = [];
  frame.forEach((row, y) => {
    [...row].forEach((ch, x) => {
      if (palette[ch]) rects.push(<rect key={`${x}-${y}`} x={x * cell} y={y * cell} width={cell + 0.5} height={cell + 0.5} fill={palette[ch]} />);
    });
  });
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ filter:`drop-shadow(0 0 6px ${color}88)`, display:'inline-block', ...style }}>{rects}</svg>
  );
}
window.PixIcon = PixIcon;

// ── Rank helper ─────────────────────────────────────────────────────
function getRank(score, max, ranks) {
  const pct = Math.max(0, Math.min(1, score / max));
  const idx = Math.min(ranks.length - 1, Math.floor(pct * ranks.length));
  return ranks[idx];
}
window.getRank = getRank;
