// ui.jsx — shared primitives, icon set, mock data, formatters
// Exports to window: Icon, Ring, Sparkline, Segmented, fmtUSD, fmtNum, ASSETS, STRATEGIES, MARKET_PETS, THEMES, LEVELS, xpForLevel

const ICONS = {
  home:    'M3 11.2 12 4l9 7.2M5 9.6V20h5v-6h4v6h5V9.6',
  paw:     'M12 14.5c-2.2 0-4 1.6-4 3.4 0 1.2 1 1.6 2 1.6.9 0 1.3-.4 2-.4s1.1.4 2 .4c1 0 2-.4 2-1.6 0-1.8-1.8-3.4-4-3.4ZM6.5 11.5a1.6 1.6 0 1 0 0-3.2 1.6 1.6 0 0 0 0 3.2ZM17.5 11.5a1.6 1.6 0 1 0 0-3.2 1.6 1.6 0 0 0 0 3.2ZM9.6 8.4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM14.4 8.4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z',
  market:  'M4 9h16l-1 11H5L4 9ZM8 9V7a4 4 0 0 1 8 0v2',
  spark:   'M12 3v4M12 17v4M3 12h4M17 12h4M6 6l2.5 2.5M18 18l-2.5-2.5M18 6l-2.5 2.5M6 18l2.5-2.5',
  send:    'M5 12h13M12 6l6 6-6 6',
  receive: 'M19 12H6M12 18l-6-6 6-6',
  swap:    'M7 8h11l-3-3M17 16H6l3 3',
  trade:   'M4 17l5-5 3 3 7-8M16 4h4v4',
  bolt:    'M13 3 5 13h5l-1 8 8-10h-5l1-8Z',
  fire:    'M12 3c1.5 3-1.5 4.5-1.5 7A1.5 1.5 0 0 0 12 11.5 1.5 1.5 0 0 0 13.5 10c2 1 3.5 3 3.5 5a5 5 0 0 1-10 0c0-3.5 3-6 5-12Z',
  shield:  'M12 3l7 3v5c0 4.5-3 8-7 10-4-2-7-5.5-7-10V6l7-3Z',
  check:   'M5 12.5l4.5 4.5L19 7',
  plus:    'M12 5v14M5 12h14',
  chevron: 'M9 6l6 6-6 6',
  chart:   'M4 20V10M10 20V4M16 20v-7M22 20H2',
  lock:    'M6 11V8a6 6 0 0 1 12 0v3M5 11h14v9H5z',
  cpu:     'M7 7h10v10H7zM9 3v3M15 3v3M9 18v3M15 18v3M3 9h3M3 15h3M18 9h3M18 15h3',
  star:    'M12 3l2.6 5.6L20.5 9l-4.3 4 1 6L12 16.2 6.8 19l1-6L3.5 9l5.9-.4L12 3Z',
  copy:    'M9 9h10v10H9zM5 15V5h10',
  gift:    'M4 11h16v9H4zM4 8h16v3H4zM12 8V5M12 8c-2 0-4-1-4-2.5S10 3 12 5c2-2 4-1.5 4 .5S14 8 12 8Z',
  eye:     'M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12ZM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z',
  palette: 'M12 3a9 9 0 1 0 0 18c1.5 0 2-1 2-2 0-1.5-1.5-1.5-1.5-3 0-1 .8-1.5 2-1.5h1.5A4.5 4.5 0 0 0 21 9.5C21 5.4 17 3 12 3ZM7.5 12a1.2 1.2 0 1 0 0-2.4 1.2 1.2 0 0 0 0 2.4ZM10.5 8a1.2 1.2 0 1 0 0-2.4A1.2 1.2 0 0 0 10.5 8ZM15 8a1.2 1.2 0 1 0 0-2.4A1.2 1.2 0 0 0 15 8Z',
  qr:      'M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h2v2h-2zM18 14h2v2h-2zM14 18h2v2h-2zM18 18h2v2h-2z',
  arrowUp: 'M12 19V5M6 11l6-6 6 6',
};

function Icon({ name, size = 22, color = 'currentColor', stroke = 2, fill = 'none', style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke={color}
         strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={style}>
      <path d={ICONS[name] || ''} />
    </svg>
  );
}

// XP / progress ring
function Ring({ size = 56, stroke = 5, value = 0, track = 'rgba(0,0,0,.08)', color = 'var(--violet)', children }) {
  const r = (size - stroke) / 2, c = 2 * Math.PI * r;
  return (
    <div style={{ width: size, height: size, position: 'relative', display: 'grid', placeItems: 'center' }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)', position: 'absolute', inset: 0 }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={track} strokeWidth={stroke} />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color} strokeWidth={stroke}
                strokeLinecap="round" strokeDasharray={c} strokeDashoffset={c * (1 - Math.min(1, value))}
                style={{ transition: 'stroke-dashoffset .7s cubic-bezier(.4,1.3,.5,1)' }} />
      </svg>
      <div style={{ position: 'relative', zIndex: 1, display: 'grid', placeItems: 'center' }}>{children}</div>
    </div>
  );
}

function Sparkline({ data, w = 100, h = 34, color = 'var(--mint)', fill = true }) {
  const min = Math.min(...data), max = Math.max(...data), rng = max - min || 1;
  const pts = data.map((d, i) => [(i / (data.length - 1)) * w, h - ((d - min) / rng) * (h - 6) - 3]);
  const line = pts.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' ');
  const area = `${line} L${w} ${h} L0 ${h} Z`;
  const gid = 'sg' + Math.round(data[0] * 1000 + w);
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      <defs><linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stopColor={color} stopOpacity="0.22" /><stop offset="1" stopColor={color} stopOpacity="0" />
      </linearGradient></defs>
      {fill && <path d={area} fill={`url(#${gid})`} />}
      <path d={line} fill="none" stroke={color} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function Segmented({ options, value, onChange, accent = 'var(--violet)' }) {
  return (
    <div style={{ display: 'flex', gap: 4, background: 'var(--bg-2)', borderRadius: 'var(--r-pill)', padding: 4 }}>
      {options.map((o) => {
        const v = o.value ?? o, label = o.label ?? o, on = v === value;
        return (
          <button key={v} onClick={() => onChange(v)} style={{
            flex: 1, border: 'none', cursor: 'pointer', padding: '9px 10px', borderRadius: 'var(--r-pill)',
            fontFamily: 'var(--body)', fontWeight: 700, fontSize: 13, letterSpacing: '.1px',
            background: on ? 'var(--surface)' : 'transparent', color: on ? 'var(--ink)' : 'var(--ink-2)',
            boxShadow: on ? '0 2px 8px rgba(45,30,70,.12)' : 'none', transition: 'all .2s',
          }}>{label}</button>
        );
      })}
    </div>
  );
}

const fmtUSD = (n, dp = 2) => '$' + n.toLocaleString('en-US', { minimumFractionDigits: dp, maximumFractionDigits: dp });
const fmtNum = (n) => n >= 1e6 ? (n / 1e6).toFixed(2) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'K' : '' + n;

// ── mock data ───────────────────────────────────────────────────
const ASSETS = [
  { sym: 'ETH', name: 'Ethereum', amt: 3.842, price: 3120.55, hue: 255, chg: 2.4, spark: [40, 42, 41, 45, 44, 48, 47, 52, 55] },
  { sym: 'SOL', name: 'Solana', amt: 128.5, price: 178.20, hue: 165, chg: 5.1, spark: [30, 32, 31, 35, 40, 38, 44, 47, 50] },
  { sym: 'USDC', name: 'USD Coin', amt: 4210.0, price: 1.00, hue: 230, chg: 0.0, spark: [50, 50, 50, 50, 50, 50, 50, 50, 50] },
  { sym: 'WBTC', name: 'Wrapped BTC', amt: 0.094, price: 68420.0, hue: 40, chg: -1.2, spark: [55, 54, 56, 53, 52, 50, 51, 49, 48] },
];

// agent-harness strategies for the strategy marketplace
const STRATEGIES = [
  { id: 's1', name: 'Delta-Neutral Drift', author: 'velora.eth', hue: 165, apy: 18.4, win: 71, risk: 'Low', price: 0.42, sub: 24, runs: '1.2K', model: 'Claude-class agent', spark: [20, 22, 24, 23, 27, 30, 33, 36, 40], tags: ['Hedged', 'Stable'] },
  { id: 's2', name: 'Momentum Hunter', author: 'kairo.eth', hue: 40, apy: 47.9, win: 58, risk: 'High', price: 1.10, sub: 61, runs: '4.7K', model: 'Multi-agent swarm', spark: [20, 28, 24, 36, 30, 44, 38, 52, 60], tags: ['Trend', 'Aggressive'] },
  { id: 's3', name: 'Stable Yield Loom', author: 'meadow.eth', hue: 285, apy: 11.2, win: 83, risk: 'Low', price: 0.30, sub: 112, runs: '8.9K', model: 'Single agent + RAG', spark: [22, 23, 25, 26, 27, 29, 30, 32, 34], tags: ['Yield', 'Safe'] },
  { id: 's4', name: 'Volatility Surfer', author: 'nyx.eth', hue: 350, apy: 33.6, win: 64, risk: 'Med', price: 0.78, sub: 38, runs: '2.1K', model: 'Agent + signals', spark: [25, 30, 26, 34, 31, 40, 36, 45, 48], tags: ['Options', 'Active'] },
];

// creatures listed on the pet market (reputation/track-record)
const MARKET_PETS = [
  { id: 'p1', name: 'Mochi', hue: 165, stage: 3, level: 42, trades: '3.4K', price: 2.8, rarity: 'Legendary' },
  { id: 'p2', name: 'Pip', hue: 40, stage: 2, level: 19, trades: '820', price: 0.6, rarity: 'Rare' },
  { id: 'p3', name: 'Glim', hue: 285, stage: 3, level: 38, trades: '2.9K', price: 2.1, rarity: 'Epic' },
  { id: 'p4', name: 'Tuff', hue: 230, stage: 2, level: 24, trades: '1.1K', price: 0.9, rarity: 'Rare' },
];

const THEMES = [
  { id: 'grape', name: 'Grape Soda', hue: 285, c1: '#9B82FF', c2: '#C9B6FF' },
  { id: 'mint', name: 'Mint Cream', hue: 165, c1: '#3FD6A0', c2: '#A8EFD6' },
  { id: 'peach', name: 'Peach Fizz', hue: 40, c1: '#FF9D6B', c2: '#FFCBA8' },
  { id: 'sky', name: 'Blue Razz', hue: 230, c1: '#4FB0F0', c2: '#A8D8F7' },
  { id: 'bubble', name: 'Bubblegum', hue: 350, c1: '#FF8AC4', c2: '#FFC2E2' },
  { id: 'butter', name: 'Lemon Drop', hue: 95, c1: '#FFCF4D', c2: '#FFE9A8' },
];

// leveling curve
const xpForLevel = (lvl) => Math.round(120 * Math.pow(lvl, 1.35));
const LEVELS = { evolveAt: [10, 25] }; // stage 1→2 at L10, 2→3 at L25

Object.assign(window, { Icon, Ring, Sparkline, Segmented, fmtUSD, fmtNum, ASSETS, STRATEGIES, MARKET_PETS, THEMES, LEVELS, xpForLevel });
