/* global React */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ---------- Helpers ----------
const fmtPrice = (v) => {
  if (v == null) return '–';
  if (v < 10) return v.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 });
  return v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};
const fmtPct = (v, digits = 2) => {
  if (v == null) return '–';
  const s = v.toFixed(digits);
  return (v > 0 ? '+' : '') + s + '%';
};
const fmtUSD = (v) => {
  if (v == null) return '–';
  if (v >= 1e9) return '$' + (v / 1e9).toFixed(1) + 'B';
  if (v >= 1e6) return '$' + (v / 1e6).toFixed(1) + 'M';
  if (v >= 1e3) return '$' + (v / 1e3).toFixed(0) + 'K';
  return '$' + v.toFixed(0);
};
const fmtKRW = (usd, rate = 1380) => {
  const krw = usd * rate;
  if (krw >= 1e8) return (krw / 1e8).toFixed(1) + '억원';
  if (krw >= 1e4) return Math.round(krw / 1e4).toLocaleString() + '만원';
  return Math.round(krw).toLocaleString() + '원';
};
const upDown = (v) => (v > 0 ? 'up' : v < 0 ? 'down' : 'neutral');
const upDownClass = (v) => (v > 0 ? 'c-up' : v < 0 ? 'c-down' : 'c-fg2');

// ---------- Coin avatar ----------
const COIN_COLORS = {
  tesla: ['#e82127', '#a8141a'],
  nvidia: ['#76b900', '#5a9000'],
  apple: ['#374151', '#1f2937'],
  microsoft: ['#0078d4', '#005a9e'],
  spy: ['#3182f6', '#1b64da'],
  qqq: ['#6a5cf2', '#4b3fc8'],
  ousg: ['#0f766e', '#0a5853'],
  buidl: ['#1c1c1e', '#000000'],
  sdai: ['#f4b731', '#d99c1e'],
  paxg: ['#c69a3a', '#9c7727'],
  coin: ['#0052ff', '#0040c4'],
  meta: ['#0668e1', '#054ab2'],
};
function Coin({ id, symbol, size }) {
  const cls = 'coin' + (size === 'lg' ? ' coin--lg' : size === 'sm' ? ' coin--sm' : '');
  const [a, b] = COIN_COLORS[id] || ['#3182f6', '#1b64da'];
  const label = symbol.replace(/^x/, '').slice(0, 3).toUpperCase();
  return (
    <div className={cls} style={{ background: `linear-gradient(135deg, ${a}, ${b})` }}>
      {label}
    </div>
  );
}

// ---------- Sparkline ----------
function Sparkline({ data, color, fill, width = 80, height = 28, strokeWidth = 1.6 }) {
  if (!data || data.length === 0) return null;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const stepX = width / (data.length - 1);
  const points = data.map((v, i) => [i * stepX, height - ((v - min) / range) * (height - 4) - 2]);
  const d = points.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const dFill = d + ` L${width},${height} L0,${height} Z`;
  return (
    <svg viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" className="spark">
      {fill && <path d={dFill} fill={fill} opacity="0.16" />}
      <path d={d} fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// ---------- Premium gauge (Toss-style horizontal bar) ----------
function PremiumGauge({ value, max = 3 }) {
  const clamped = Math.max(-max, Math.min(max, value));
  const pct = (clamped + max) / (2 * max);
  const color = value > 0.05 ? 'var(--up)' : value < -0.05 ? 'var(--down)' : 'var(--neutral)';
  return (
    <div style={{ position: 'relative', height: 10, background: 'var(--bg-muted)', borderRadius: 999, overflow: 'visible' }}>
      <div style={{ position: 'absolute', left: '50%', top: -2, bottom: -2, width: 1, background: 'var(--line)' }} />
      <div style={{
        position: 'absolute',
        left: `${Math.min(50, pct * 100)}%`,
        right: `${100 - Math.max(50, pct * 100)}%`,
        top: 0, bottom: 0,
        background: color,
        borderRadius: 999,
      }} />
      <div style={{
        position: 'absolute',
        left: `calc(${pct * 100}% - 8px)`,
        top: -3,
        width: 16, height: 16, borderRadius: '50%',
        background: 'white', border: `3px solid ${color}`,
        boxShadow: '0 1px 4px rgba(0,0,0,0.08)',
      }} />
    </div>
  );
}

// ---------- Icons (minimal inline svgs) ----------
const Icon = {
  search: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>),
  bell: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9Z" /><path d="M10 21a2 2 0 0 0 4 0" /></svg>),
  home: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 12 12 4l9 8" /><path d="M5 10v10h14V10" /></svg>),
  market: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 17 9 11l4 4 8-8" /><path d="M14 7h7v7" /></svg>),
  wallet: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="6" width="18" height="14" rx="2" /><path d="M16 13h2" /><path d="M3 10h18" /></svg>),
  chat: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 12c0-4.4 4-8 9-8s9 3.6 9 8-4 8-9 8c-1.2 0-2.3-.2-3.3-.6L3 21l1.6-4.2A7.7 7.7 0 0 1 3 12Z" /></svg>),
  star: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m12 3 2.6 6 6.4.6-4.8 4.3 1.4 6.3L12 17l-5.6 3.2L7.8 14 3 9.6l6.4-.6L12 3Z"/></svg>),
  starFill: (p) => (<svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="m12 3 2.6 6 6.4.6-4.8 4.3 1.4 6.3L12 17l-5.6 3.2L7.8 14 3 9.6l6.4-.6L12 3Z"/></svg>),
  arrow: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m9 6 6 6-6 6"/></svg>),
  arrowLeft: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m15 18-6-6 6-6"/></svg>),
  flame: (p) => (<svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2s4 4 4 8a4 4 0 1 1-8 0c0-1 .3-1.8.8-2.6C9.4 8 9 9 9 10c-2 0-3 1.5-3 4a6 6 0 0 0 12 0c0-5-6-8-6-12Z"/></svg>),
  trend: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 17 9 11l4 4 8-8"/></svg>),
  shield: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3 4 6v6c0 5 3.5 8 8 9 4.5-1 8-4 8-9V6l-8-3Z"/></svg>),
  chart: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 3v18h18"/><path d="M7 14v4"/><path d="M12 9v9"/><path d="M17 5v13"/></svg>),
  globe: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a14 14 0 0 1 0 18"/><path d="M12 3a14 14 0 0 0 0 18"/></svg>),
};

// Export to window for cross-file scope
Object.assign(window, {
  fmtPrice, fmtPct, fmtUSD, fmtKRW, upDown, upDownClass,
  Coin, Sparkline, PremiumGauge, Icon,
});
