// ui.jsx — shared UI atoms (riso aesthetic, theme-aware).

function H({ theme, children, size = 36, color, align = 'left', style = {} }) {
  return (
    <div style={{
      fontFamily: theme.fontDisplay, fontSize: size, lineHeight: 0.95,
      color: color || theme.fg, letterSpacing: '-0.01em',
      textAlign: align, ...style,
    }}>{children}</div>
  );
}

function RetroBtn({ theme, children, onClick, variant = 'primary', size = 'lg', disabled, style = {} }) {
  const colors = {
    primary: { bg: theme.primary, fg: theme.mode === 'dark' ? '#fff' : theme.fg, border: theme.fg },
    yellow:  { bg: theme.yellow,  fg: theme.mode === 'dark' ? '#0d0d10' : theme.fg, border: theme.fg },
    cyan:    { bg: theme.cyan,    fg: theme.mode === 'dark' ? '#0d0d10' : theme.fg, border: theme.fg },
    ghost:   { bg: 'transparent', fg: theme.fg, border: theme.fg },
    danger:  { bg: theme.red,     fg: '#fff', border: theme.fg },
    success: { bg: theme.green,   fg: theme.mode === 'dark' ? '#0d0d10' : theme.fg, border: theme.fg },
    surface: { bg: theme.surface, fg: theme.fg, border: theme.fg },
  };
  const c = colors[variant] || colors.primary;
  const h = size === 'lg' ? 56 : size === 'md' ? 44 : 32;
  return (
    <button
      onClick={onClick} disabled={disabled}
      style={{
        height: h, padding: '0 18px',
        background: c.bg, color: c.fg,
        border: `2.5px solid ${c.border}`,
        borderRadius: theme.radius,
        fontFamily: theme.fontHead, fontSize: 16, fontWeight: 900,
        letterSpacing: '0.06em', textTransform: 'uppercase',
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.45 : 1,
        boxShadow: `0 4px 0 0 ${theme.fg}`,
        transition: 'transform .08s, box-shadow .08s',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        width: style.width || 'auto', ...style,
      }}
      onPointerDown={(e) => { e.currentTarget.style.transform = 'translateY(2px)'; e.currentTarget.style.boxShadow = `0 2px 0 0 ${theme.fg}`; }}
      onPointerUp={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}
      onPointerLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}
    >
      {children}
    </button>
  );
}

function Card({ theme, children, color, padded = true, accent, style = {} }) {
  return (
    <div style={{
      background: color || theme.surface,
      border: `2px solid ${theme.fg}`,
      borderRadius: theme.radius,
      boxShadow: accent ? `4px 4px 0 0 ${accent}` : `0 4px 0 0 ${theme.fg}`,
      padding: padded ? 14 : 0,
      color: theme.fg,
      ...style,
    }}>{children}</div>
  );
}

function Pinyin({ theme, children, size = 48, color, style = {} }) {
  // Lesson data uses "—" as a placeholder for distractor-options' pinyin
  // (intentionally ungrammatical wrong answers). Skip rendering those.
  if (children == null || children === '' || children === '—') return null;
  return (
    <span className="pinyin" style={{
      fontFamily: theme.fontPinyin, fontSize: size, fontWeight: 700,
      color: color || theme.fg, letterSpacing: 0, lineHeight: 1, ...style,
    }}>{children}</span>
  );
}

// Chinese-character display — uses a serif/CJK stack and a different size scale.
function CN({ theme, children, size = 48, color, style = {} }) {
  return (
    <span style={{
      fontFamily: theme.fontCN, fontSize: size, fontWeight: 700,
      color: color || theme.fg, lineHeight: 1.05, ...style,
    }}>{children}</span>
  );
}

function Bar({ theme, value, max = 1, height = 12 }) {
  const pct = Math.max(0, Math.min(100, (value / max) * 100));
  return (
    <div style={{
      height, background: theme.surfaceAlt,
      border: `2px solid ${theme.fg}`,
      borderRadius: 999, overflow: 'hidden', position: 'relative',
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        background: theme.primary, width: `${pct}%`, transition: 'width .25s',
      }} />
    </div>
  );
}

function ScoreBar({ theme, progress }) {
  return (
    <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
      <ScoreChip theme={theme} icon={<Flame theme={theme} size={16}/>} label="STREAK"  value={progress.streak} accent={theme.red}/>
      <ScoreChip theme={theme} icon={<Coin theme={theme} size={16}/>}  label="COINS"   value={progress.coins}  accent={theme.yellow}/>
      <ScoreChip theme={theme} label="HI SCORE" value={String(progress.highScore)} accent={theme.primary}/>
    </div>
  );
}

function ScoreChip({ theme, icon, label, value, accent }) {
  return (
    <div style={{
      flex: 1, background: theme.surface,
      border: `2px solid ${theme.fg}`, borderRadius: theme.radius,
      padding: '6px 8px',
      display: 'flex', flexDirection: 'column', gap: 2,
      boxShadow: `0 2px 0 0 ${accent}`,
    }}>
      <div style={{
        fontFamily: theme.fontHead, fontSize: 10, letterSpacing: '0.1em',
        color: theme.fgMute, display: 'flex', alignItems: 'center', gap: 4,
        textTransform: 'uppercase',
      }}>{icon}{label}</div>
      <div style={{
        fontFamily: theme.fontDisplay, fontSize: 22, fontWeight: 900,
        color: theme.fg, lineHeight: 1, fontVariantNumeric: 'tabular-nums',
      }}>{value}</div>
    </div>
  );
}

function TabBar({ theme, tab, onTab }) {
  const tabs = [
    { id: 'home',    label: 'LEARN',  icon: 'home' },
    { id: 'drill',   label: 'DRILL',  icon: 'drill' },
    { id: 'tutor',   label: 'TUTOR',  icon: 'tutor' },
    { id: 'profile', label: 'YOU',    icon: 'you' },
    { id: 'settings',label: 'SET',    icon: 'set' },
  ];
  return (
    <div style={{
      display: 'flex', background: theme.surface,
      borderTop: `2px solid ${theme.fg}`,
      padding: '6px 4px 24px',
    }}>
      {tabs.map((t) => {
        const active = tab === t.id;
        return (
          <button key={t.id} onClick={() => onTab(t.id)}
            style={{
              flex: 1, border: 0, background: 'transparent',
              padding: '6px 0',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
              color: active ? theme.primary : theme.fgMute,
              cursor: 'pointer',
            }}>
            <TabIcon theme={theme} icon={t.icon} active={active} />
            <div style={{
              fontFamily: theme.fontHead, fontSize: 9, fontWeight: 900,
              letterSpacing: '0.08em',
            }}>{t.label}</div>
          </button>
        );
      })}
    </div>
  );
}

function TabIcon({ theme, icon, active }) {
  const c = active ? theme.primary : theme.fgMute;
  const sw = 2.2;
  switch (icon) {
    case 'home': return (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <path d="M3 11 L12 3 L21 11 L21 21 L14 21 L14 14 L10 14 L10 21 L3 21 Z"
              stroke={c} strokeWidth={sw} strokeLinejoin="round"
              fill={active ? theme.primary : 'none'} fillOpacity={active ? 0.15 : 0}/>
      </svg>
    );
    case 'drill': return (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <path d="M3 16 Q 9 8, 12 16 T 21 16" stroke={c} strokeWidth={sw} fill="none" strokeLinecap="round"/>
        <circle cx="12" cy="6" r="2" fill={c}/>
      </svg>
    );
    case 'tutor': return (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <path d="M4 5 L20 5 L20 16 L13 16 L9 20 L9 16 L4 16 Z"
              stroke={c} strokeWidth={sw} strokeLinejoin="round"
              fill={active ? theme.primary : 'none'} fillOpacity={active ? 0.15 : 0}/>
        <circle cx="9" cy="10.5" r="1.2" fill={c}/>
        <circle cx="13" cy="10.5" r="1.2" fill={c}/>
        <circle cx="17" cy="10.5" r="1.2" fill={c}/>
      </svg>
    );
    case 'you': return (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <circle cx="12" cy="8" r="4" stroke={c} strokeWidth={sw}
                fill={active ? theme.primary : 'none'} fillOpacity={active ? 0.15 : 0}/>
        <path d="M4 21 Q 4 14 12 14 Q 20 14 20 21" stroke={c} strokeWidth={sw} strokeLinecap="round" fill="none"/>
      </svg>
    );
    case 'set': return (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <circle cx="12" cy="12" r="3" stroke={c} strokeWidth={sw}/>
        <path d="M12 2 L12 5 M12 19 L12 22 M2 12 L5 12 M19 12 L22 12 M5 5 L7 7 M17 17 L19 19 M5 19 L7 17 M17 7 L19 5"
              stroke={c} strokeWidth={sw} strokeLinecap="round"/>
      </svg>
    );
  }
}

function ToneCurve({ tone, theme, size = 36, color }) {
  const c = color || theme.fg;
  const paths = [
    'M2 6 L34 6',
    'M2 30 L34 6',
    'M2 12 Q 12 30 18 22 Q 26 14 34 24',
    'M2 6 L34 30',
  ];
  return (
    <svg viewBox="0 0 36 36" width={size} height={size} style={{ display: 'block' }}>
      <path d={paths[tone]} stroke={c} strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
      <polygon
        points={tone === 0 ? '34,3 34,9 38,6'
              : tone === 1 ? '34,3 38,6 33,9'
              : tone === 2 ? '34,21 38,24 33,27'
              : '34,27 38,30 33,33'}
        fill={c}/>
    </svg>
  );
}

function StarRow({ theme, count = 0, max = 3, size = 22 }) {
  return (
    <div style={{ display: 'flex', gap: 4 }}>
      {Array.from({ length: max }).map((_, i) => (
        <Star key={i} theme={theme} size={size} filled={i < count} />
      ))}
    </div>
  );
}

// Phone-like screen container — establishes the motif background, padding.
function Screen({ theme, children, padHeader = 16, scroll = true, style = {} }) {
  return (
    <div style={{
      width: '100%', height: '100%',
      background: motifBg(theme), backgroundColor: theme.bg,
      color: theme.fg,
      display: 'flex', flexDirection: 'column',
      overflow: scroll ? 'hidden' : 'visible',
      position: 'relative',
      ...style,
    }}>
      {children}
    </div>
  );
}

// A small infer of best tone in a syllable for pronunciation hints.
function inferTone(py) {
  if (!py) return 0;
  const ch = py.toLowerCase();
  if (/[āēīōūǖ]/.test(ch)) return 0;
  if (/[áéíóúǘ]/.test(ch)) return 1;
  if (/[ǎěǐǒǔǚ]/.test(ch)) return 2;
  if (/[àèìòùǜ]/.test(ch)) return 3;
  return 0;
}

// Scroll-position cache, keyed by screen name. Lets us preserve where the
// user was on Home/Profile/etc. after they go into a lesson and come back.
// Lives on window so navigations don't blow it away.
window._chopstickScroll = window._chopstickScroll || {};

function useScrollMemory(key) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const saved = window._chopstickScroll?.[key];
    if (saved != null && ref.current) ref.current.scrollTop = saved;
  }, [key]);
  const onScroll = React.useCallback((e) => {
    window._chopstickScroll[key] = e.currentTarget.scrollTop;
  }, [key]);
  return [ref, onScroll];
}

function resetScrollMemory(key) {
  if (window._chopstickScroll) delete window._chopstickScroll[key];
}

// Normalize pinyin for type-pinyin grading.
function normalizePinyin(s) {
  if (!s) return '';
  return s.toLowerCase()
    .replace(/\s+/g, '')
    .replace(/[āáǎà]/g, 'a').replace(/[ēéěè]/g, 'e').replace(/[īíǐì]/g, 'i')
    .replace(/[ōóǒò]/g, 'o').replace(/[ūúǔù]/g, 'u').replace(/[ǖǘǚǜü]/g, 'v')
    .replace(/[^a-z0-9]/g, '');
}

Object.assign(window, {
  H, RetroBtn, Card, Pinyin, CN, Bar, ScoreBar, ScoreChip, TabBar, TabIcon,
  ToneCurve, StarRow, Screen, inferTone, normalizePinyin,
  useScrollMemory, resetScrollMemory,
});
