/* ═══════════════════════════════════════════════════════
   shell · Avatar, Ticker, TopBar, Drawer, FAB, Toast, QR
   All shared UI primitives. Reads from S (store).
═══════════════════════════════════════════════════════ */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ── Avatar (deterministic color by name hash) ─────── */
const AVATAR_HUES = [28, 210, 0, 142, 270, 320, 50, 180, 100, 240, 12, 200];
function nameHue(name) {
  let h = 0;
  for (let i = 0; i < (name || '').length; i++) h = (name.charCodeAt(i) + ((h << 5) - h)) >>> 0;
  return AVATAR_HUES[Math.abs(h) % AVATAR_HUES.length];
}
const Avatar = ({ name, src, size = 36, ring = false, hue, syncState, online }) => {
  const useHue = hue ?? nameHue(name || '?');
  const syncColors = { ok: 'var(--neon)', saving: 'var(--gold-1)', error: 'var(--red-1)' };
  const syncColor = syncState ? syncColors[syncState] || 'var(--neon)' : null;
  const dotSize = Math.max(8, Math.round(size * 0.26));
  const style = {
    width: size, height: size,
    fontSize: Math.round(size * 0.36),
    background: src ? '#111' : `linear-gradient(135deg, hsl(${useHue} 52% 36%) 0%, hsl(${(useHue+40)%360} 38% 22%) 100%)`,
    color: 'var(--ink)',
    border: syncColor ? `2px solid ${syncColor}` : ring ? '2px solid var(--gold)' : '1.5px solid var(--border)',
    boxShadow: syncColor
      ? (syncState === 'saving' ? `0 0 0 3px ${syncColor}44` : syncState === 'ok' ? `0 0 0 2px ${syncColor}33` : `0 0 0 2px ${syncColor}44`)
      : ring ? '0 0 0 3px var(--gold-soft)' : 'none',
    transition: 'border-color 0.3s ease, box-shadow 0.3s ease',
    position: 'relative',
  };
  return (
    <div className="avatar" style={style} title={syncState === 'saving' ? 'Salvando...' : syncState === 'error' ? 'Erro ao salvar' : undefined}>
      {src ? <img src={src} alt={name}/> : initials(name)}
      {syncState === 'saving' && (
        <div style={{
          position: 'absolute', inset: -3, borderRadius: '50%',
          border: `2px solid ${syncColor}`,
          animation: 'pulseRing 1.4s ease-out infinite',
          pointerEvents: 'none',
        }}/>
      )}
      {online && (
        <div style={{
          position: 'absolute',
          bottom: -1, right: -1,
          width: dotSize, height: dotSize,
          borderRadius: '50%',
          background: 'var(--neon)',
          border: `${Math.max(1, Math.round(dotSize * 0.2))}px solid var(--bg)`,
          boxShadow: '0 0 6px var(--neon), 0 0 12px rgba(0,255,157,0.4)',
          animation: 'pulseOnline 2.5s ease-in-out infinite',
          pointerEvents: 'none',
        }}/>
      )}
    </div>
  );
};

/* ── Animated counters ───────────────────────── */
const Ticker = ({ value, prefix = '', suffix = '', decimals = 0, duration = 700, style }) => {
  const [display, setDisplay] = useState(value);
  useEffect(() => {
    const from = display, to = Number(value) || 0;
    if (from === to) return;
    const t0 = performance.now();
    let raf;
    const step = t => {
      const k = Math.min(1, (t - t0) / duration);
      const e = 1 - Math.pow(1 - k, 3);
      setDisplay(from + (to - from) * e);
      if (k < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [value]);
  const num = decimals > 0 ? display.toFixed(decimals) : Math.round(display).toString();
  return <span className="ticker" style={style}>{prefix}{num.replace(/\B(?=(\d{3})+(?!\d))/g, '.')}{suffix}</span>;
};
const TickerBRL = ({ value, style }) => {
  const [display, setDisplay] = useState(value);
  useEffect(() => {
    const from = display, to = Number(value) || 0;
    if (from === to) return;
    const t0 = performance.now(), dur = 700;
    let raf;
    const step = t => {
      const k = Math.min(1, (t - t0) / dur);
      const e = 1 - Math.pow(1 - k, 3);
      setDisplay(from + (to - from) * e);
      if (k < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [value]);
  return <span className="ticker" style={style}>{fmtBRL(display)}</span>;
};

/* ── Confetti one-shot ─────────────────────── */
const Confetti = ({ run, host = '.viewport' }) => {
  useEffect(() => {
    if (!run) return;
    const colors = ['#d4af37', '#f4d160', '#d63449', '#00ff9d', '#36e2ff', '#f5efde'];
    const container = document.querySelector(host);
    if (!container) return;
    const bits = [];
    for (let i = 0; i < 90; i++) {
      const el = document.createElement('div');
      el.className = 'confetti-bit';
      el.style.left = Math.random() * 100 + '%';
      el.style.background = colors[i % colors.length];
      el.style.transform = `rotate(${Math.random() * 360}deg)`;
      el.style.animationDuration = (2.2 + Math.random() * 2) + 's';
      el.style.animationDelay = (Math.random() * 0.5) + 's';
      el.style.borderRadius = Math.random() > 0.6 ? '50%' : '2px';
      el.style.width = (6 + Math.random() * 8) + 'px';
      el.style.height = (8 + Math.random() * 12) + 'px';
      container.appendChild(el); bits.push(el);
    }
    const t = setTimeout(() => bits.forEach(b => b.remove()), 5200);
    return () => { clearTimeout(t); bits.forEach(b => b.remove()); };
  }, [run]);
  return null;
};

/* ── Sparkline ─────────────────────────────── */
const Sparkline = ({ data, color = 'var(--gold-1)', width = 80, height = 26, fill = true }) => {
  if (!data || data.length < 2) return null;
  const max = Math.max(...data), min = Math.min(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => [
    (i / (data.length - 1)) * width,
    height - ((v - min) / range) * (height - 4) - 2,
  ]);
  const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const fillPath = path + ` L${width},${height} L0,${height} Z`;
  return (
    <svg width={width} height={height} style={{ display: 'block' }}>
      {fill && <path d={fillPath} fill={color} opacity="0.18"/>}
      <path d={path} fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
      <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="2.2" fill={color}/>
    </svg>
  );
};

/* ── Stat card ─────────────────────────────── */
const Stat = ({ label, value, color = 'var(--ink)', icon, sub, big = false }) => (
  <div className="card" style={{ padding: big ? 16 : 12, position: 'relative', overflow: 'hidden', minWidth: 0 }}>
    {icon && (
      <div style={{ position: 'absolute', top: 10, right: 10, opacity: 0.25, color }}>
        <Icon name={icon} size={26}/>
      </div>
    )}
    <div className="eyebrow" style={{ marginBottom: 6 }}>{label}</div>
    <div className="font-mono" style={{ color, fontSize: big ? 28 : 15, fontWeight: 700, letterSpacing: '-0.01em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '100%' }}>
      {value}
    </div>
    {sub && <div style={{ color: 'var(--ink-3)', fontSize: 11, marginTop: 4 }}>{sub}</div>}
  </div>
);

/* ── Suit corner decor ─────────────────────── */
const SuitsCorner = ({ pos = 'tr', opacity = 0.04 }) => {
  const styleMap = {
    tr: { top: -30, right: -30, transform: 'rotate(12deg)' },
    bl: { bottom: -40, left: -30, transform: 'rotate(-18deg)' },
    tl: { top: -20, left: -20, transform: 'rotate(-8deg)' },
    br: { bottom: -30, right: -20, transform: 'rotate(20deg)' },
  };
  return (
    <div style={{
      position: 'absolute',
      pointerEvents: 'none',
      opacity, color: 'var(--gold-1)',
      ...styleMap[pos],
    }}>
      <Suit kind="spade" size={180}/>
    </div>
  );
};

/* ── Top Bar (sticky) ──────────────────────── */
const TopBar = ({ title, subtitle, onMenu, right, back, onBack, transparent = false }) => (
  <div className="topbar" style={transparent ? { background: 'transparent', backdropFilter: 'none' } : {}}>
    {back ? (
      <button className="topbar-icon-btn" onClick={onBack}>
        <Icon name="back" size={20}/>
      </button>
    ) : (
      <button className="topbar-icon-btn" onClick={onMenu}>
        <Icon name="menu" size={20}/>
      </button>
    )}
    <div style={{ flex: 1, minWidth: 0 }}>
      {subtitle && (
        <div style={{ fontSize: 10, letterSpacing: '0.18em', color: 'var(--ink-3)', textTransform: 'uppercase', fontWeight: 600 }}>
          {subtitle}
        </div>
      )}
      <div style={{
        fontFamily: 'var(--font-editorial)', fontStyle: 'italic',
        fontSize: 22, color: 'var(--ink)', lineHeight: 1.1,
        overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
      }}>{title}</div>
    </div>
    {right}
  </div>
);

/* ── Drawer ────────────────────────────────── */
const DRAWER_ITEMS_ALL = [
  { id: 'home',       label: 'Início',       icon: 'home' },
  { id: 'ranking',    label: 'Ranking',      icon: 'trophy' },
  { id: 'partidas',   label: 'Partidas',     icon: 'cards' },
  { id: 'seasons',    label: 'Temporadas',   icon: 'calendar', adminOnly: true },
  { id: 'mensalistas',label: 'Mensalistas',  icon: 'wallet', adminOnly: true },
  { id: 'usuarios',   label: 'Usuários',     icon: 'users', adminOnly: true },
  { id: 'perfil',     label: 'Meu Perfil',   icon: 'user' },
];

const Drawer = () => {
  const s = useStore();
  if (!s.drawerOpen) return null;
  const me = s.allUsers.find(u => u.uid === s.userUid) || {};
  const open = s.games.filter(g => g.status === 'open').length;
  const items = DRAWER_ITEMS_ALL.filter(i => !i.adminOnly || isAdmin());
  const close = () => update({ drawerOpen: false });
  const nav = id => update({ drawerOpen: false, route: id, currentGame: null });
  const switchClub = () => update({ drawerOpen: false, screen: 'clubs', currentClubId: null, currentGame: null });
  return (
    <>
      <div className="drawer-backdrop" onClick={close}/>
      <div className="drawer">
        {/* header */}
        <div style={{ padding: '20px 18px 18px', borderBottom: '1px solid var(--border-2)' }}>
          <div className="row" style={{ marginBottom: 14 }}>
            <div style={{ position: 'relative' }}>
              <Avatar name={me.displayName || me.email} src={me.avatar} size={48} ring syncState={s.sync} online={isOnline(me)}/>
            </div>
            <div style={{ flex: 1, marginLeft: 12, minWidth: 0 }}>
              <div style={{ color: 'var(--ink)', fontWeight: 700, fontSize: 15 }}>
                {me.displayName || (me.email || '').split('@')[0]}
              </div>
              <div style={{ color: 'var(--ink-3)', fontSize: 12, overflow: 'hidden', textOverflow: 'ellipsis' }}>{me.email}</div>
            </div>
            <button className="topbar-icon-btn" onClick={close} style={{ width: 32, height: 32 }}>
              <Icon name="close" size={18}/>
            </button>
          </div>
          {/* club selector */}
          <button onClick={switchClub} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            width: '100%', background: 'var(--gold-soft)',
            border: '1px solid var(--border-strong)', borderRadius: 'var(--radius)',
            padding: '10px 12px', textAlign: 'left',
          }}>
            <div style={{
              width: 36, height: 36, borderRadius: 9,
              background: 'linear-gradient(135deg, var(--gold) 0%, var(--felt-deep) 100%)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: 'var(--gold-1)', overflow: 'hidden',
            }}>
              {s.clubInfo?.logo
                ? <img src={s.clubInfo.logo} style={{ width: '100%', height: '100%', objectFit: 'cover' }}/>
                : <Suit kind="spade" size={20}/>}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ color: 'var(--gold-1)', fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase' }}>Clube</div>
              <div style={{ color: 'var(--ink)', fontWeight: 700, fontSize: 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                {s.clubInfo?.name || 'Selecionar…'}
              </div>
            </div>
            <Icon name="chevron-down" size={18} style={{ color: 'var(--ink-3)' }}/>
          </button>
        </div>

        <div style={{ flex: 1, padding: '14px 0', overflowY: 'auto' }}>
          {items.map(it => (
            <button key={it.id}
                    className={`drawer-item ${s.route === it.id && !s.currentGame ? 'active' : ''}`}
                    onClick={() => nav(it.id)}>
              <Icon name={it.icon}/>
              <span style={{ flex: 1, textAlign: 'left' }}>{it.label}</span>
              {it.id === 'partidas' && open > 0 && <span className="chip chip-neon" style={{ fontSize: 9, padding: '2px 7px' }}>{open} aberta{open > 1 ? 's' : ''}</span>}
            </button>
          ))}
        </div>

        <div style={{ padding: '14px 18px', borderTop: '1px solid var(--border-2)' }}>
          <ThemeToggle/>
          <button onClick={() => { close(); doLogout(); }} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            width: '100%', padding: '12px 0', marginTop: 8,
            color: 'var(--ink-3)', fontSize: 13,
          }}>
            <Icon name="logout" size={18}/> Sair da conta
          </button>
          <div style={{ color: 'var(--ink-faint)', fontSize: 10, marginTop: 6, fontFamily: 'var(--font-mono)', letterSpacing: '0.1em' }}>
            v{APP_VERSION} · ROYAL FLUSH
          </div>
        </div>
      </div>
    </>
  );
};

/* ── Theme toggle ──────────────────────────── */
const ThemeToggle = () => {
  const [theme, setTheme] = useState(() =>
    document.body.classList.contains('theme-marble') ? 'marble' : 'velvet'
  );
  const toggle = t => {
    setTheme(t);
    document.body.classList.toggle('theme-marble', t === 'marble');
    try { localStorage.setItem('scp_theme', t); } catch (e) {}
  };
  return (
    <div style={{
      display: 'flex',
      background: 'var(--bg-2)', border: '1px solid var(--border)',
      borderRadius: 999, padding: 3, gap: 2,
    }}>
      <button onClick={() => toggle('velvet')} style={{
        flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        padding: '8px 10px', borderRadius: 999,
        background: theme === 'velvet' ? 'var(--gold-soft)' : 'transparent',
        color: theme === 'velvet' ? 'var(--gold-1)' : 'var(--ink-3)',
        fontSize: 12, fontWeight: 600, transition: 'all 0.2s var(--ease)',
      }}>
        <Icon name="moon" size={14}/> Velvet
      </button>
      <button onClick={() => toggle('marble')} style={{
        flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        padding: '8px 10px', borderRadius: 999,
        background: theme === 'marble' ? 'var(--gold-soft)' : 'transparent',
        color: theme === 'marble' ? 'var(--gold-1)' : 'var(--ink-3)',
        fontSize: 12, fontWeight: 600, transition: 'all 0.2s var(--ease)',
      }}>
        <Icon name="sun" size={14}/> Marble
      </button>
    </div>
  );
};

/* ── Toaster ───────────────────────────────── */
const Toaster = () => {
  const s = useStore();
  return (
    <div style={{ position: 'absolute', top: 70, left: 16, right: 16, zIndex: 80, pointerEvents: 'none' }}>
      {s.toasts.map(t => (
        <div key={t.id} className="card-lift card" style={{
          padding: '12px 14px', marginBottom: 8,
          display: 'flex', alignItems: 'center', gap: 10,
          borderColor: t.kind === 'success' ? 'var(--neon)' : t.kind === 'error' ? 'var(--red)' : 'var(--border-strong)',
          animation: 'fadeUp 0.3s var(--ease-out) both',
          background: 'var(--surface-2)',
        }}>
          <div style={{ color: t.kind === 'success' ? 'var(--neon)' : t.kind === 'error' ? 'var(--red-1)' : 'var(--gold-1)' }}>
            <Icon name={t.kind === 'success' ? 'check' : t.kind === 'error' ? 'close' : 'spark'} size={18}/>
          </div>
          <div style={{ fontSize: 13, color: 'var(--ink)', flex: 1 }}>{t.msg}</div>
        </div>
      ))}
    </div>
  );
};

/* ── QR Code (visual) ─────────────────────── */
const QRCode = ({ value, size = 200 }) => {
  const cells = 21;
  const cellSize = size / cells;
  const hash = s => { let h = 5381; for (let i = 0; i < s.length; i++) h = ((h << 5) + h) ^ s.charCodeAt(i); return h >>> 0; };
  const seed = hash(value);
  const isFinder = (r, c) => (
    (r < 7 && c < 7) || (r < 7 && c >= cells - 7) || (r >= cells - 7 && c < 7)
  );
  const cells_data = [];
  for (let r = 0; r < cells; r++) for (let c = 0; c < cells; c++)
    cells_data.push({ r, c, on: hash(`${seed}-${r}-${c}`) % 5 < 2 });
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ background: 'var(--ink)', borderRadius: 8, padding: 6 }}>
      {cells_data.map((p, i) => (
        !isFinder(p.r, p.c) && p.on && (
          <rect key={i} x={p.c * cellSize} y={p.r * cellSize} width={cellSize} height={cellSize} fill="var(--bg)"/>
        )
      ))}
      {[[0, 0], [0, cells - 7], [cells - 7, 0]].map(([r, c], i) => (
        <g key={i}>
          <rect x={c * cellSize} y={r * cellSize} width={7 * cellSize} height={7 * cellSize} fill="var(--bg)"/>
          <rect x={(c + 1) * cellSize} y={(r + 1) * cellSize} width={5 * cellSize} height={5 * cellSize} fill="var(--ink)"/>
          <rect x={(c + 2) * cellSize} y={(r + 2) * cellSize} width={3 * cellSize} height={3 * cellSize} fill="var(--bg)"/>
        </g>
      ))}
      <circle cx={size/2} cy={size/2} r={size*0.13} fill="var(--ink)"/>
      <g transform={`translate(${size/2 - 12} ${size/2 - 12})`} style={{ color: 'var(--gold-1)' }}>
        <Suit kind="spade" size={24}/>
      </g>
    </svg>
  );
};

/* ── Sync badge ───────────────────────────── */
const SyncBadge = () => {
  const s = useStore();
  const colors = { ok: 'var(--neon)', saving: 'var(--gold-1)', error: 'var(--red-1)' };
  const labels = { ok: '✓', saving: '⟳', error: '⚠' };
  return (
    <span style={{
      fontSize: 10, fontFamily: 'var(--font-mono)',
      color: colors[s.sync],
      display: 'inline-flex', alignItems: 'center', gap: 4,
    }}>
      <span style={{
        width: 6, height: 6, borderRadius: '50%',
        background: colors[s.sync],
        boxShadow: s.sync === 'saving' ? '0 0 8px var(--gold-soft)' : 'none',
        animation: s.sync === 'saving' ? 'spin 1.2s linear infinite' : 'none',
      }}/>
      {labels[s.sync]}
    </span>
  );
};

/* ── Sheet (bottom modal) wrapper ─────────── */
const Sheet = ({ children, onClose, title, eyebrow }) => (
  <div className="sheet-backdrop" onClick={onClose}>
    <div className="sheet" onClick={e => e.stopPropagation()}>
      <div className="sheet-handle"/>
      {(title || eyebrow) && (
        <div className="row" style={{ marginBottom: 14 }}>
          <div>
            {eyebrow && <div className="eyebrow" style={{ color: 'var(--gold-1)' }}>{eyebrow}</div>}
            {title && <div className="font-editorial" style={{ fontStyle: 'italic', fontSize: 22 }}>{title}</div>}
          </div>
          <span style={{ flex: 1 }}/>
          <button className="topbar-icon-btn" onClick={onClose}><Icon name="close" size={18}/></button>
        </div>
      )}
      {children}
    </div>
  </div>
);

Object.assign(window, {
  Avatar, Ticker, TickerBRL, Confetti, Sparkline, Stat, SuitsCorner, TopBar,
  Drawer, ThemeToggle, Toaster, QRCode, SyncBadge, Sheet, nameHue,
});
