/* Shared UI building blocks for ONS platform */
const { useState, useEffect, useRef, useMemo, useCallback, Fragment } = React;

// ============ ICONS ============
const Icon = ({ name, size = 14, className = '', style }) => {
  const paths = ICONS[name];
  if (!paths) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"
      stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style}>
      {paths}
    </svg>
  );
};

const ICONS = {
  search: <><circle cx="7" cy="7" r="5"/><path d="M11 11l3 3"/></>,
  bell: <><path d="M3 11l1-1V7a4 4 0 018 0v3l1 1H3z"/><path d="M6.5 13a1.5 1.5 0 003 0"/></>,
  settings: <><circle cx="8" cy="8" r="2"/><path d="M8 1v2M8 13v2M3.05 3.05l1.4 1.4M11.55 11.55l1.4 1.4M1 8h2M13 8h2M3.05 12.95l1.4-1.4M11.55 4.45l1.4-1.4"/></>,
  help: <><circle cx="8" cy="8" r="6"/><path d="M6.5 6a1.5 1.5 0 113 0c0 1-1.5 1.2-1.5 2.5"/><circle cx="8" cy="11.5" r="0.4" fill="currentColor"/></>,
  chevronDown: <path d="M4 6l4 4 4-4"/>,
  chevronRight: <path d="M6 4l4 4-4 4"/>,
  chevronLeft: <path d="M10 4L6 8l4 4"/>,
  chevronUpDown: <><path d="M5 6l3-3 3 3"/><path d="M5 10l3 3 3-3"/></>,
  plus: <><path d="M8 3v10M3 8h10"/></>,
  x: <><path d="M3 3l10 10M13 3L3 13"/></>,
  check: <path d="M3 8l3 3 7-7"/>,
  filter: <path d="M2 3h12l-4.5 6V14l-3-1.5V9L2 3z"/>,
  download: <><path d="M8 2v8M4.5 7.5L8 11l3.5-3.5"/><path d="M2 13h12"/></>,
  upload: <><path d="M8 11V3M4.5 5.5L8 2l3.5 3.5"/><path d="M2 13h12"/></>,
  refresh: <><path d="M2 4l2 2 2-2"/><path d="M4 6V4a4 4 0 014-4 4 4 0 014 4M14 12l-2-2-2 2"/><path d="M12 10v2a4 4 0 01-4 4 4 4 0 01-4-4"/></>,
  more: <><circle cx="3" cy="8" r="1" fill="currentColor"/><circle cx="8" cy="8" r="1" fill="currentColor"/><circle cx="13" cy="8" r="1" fill="currentColor"/></>,
  moreVert: <><circle cx="8" cy="3" r="1" fill="currentColor"/><circle cx="8" cy="8" r="1" fill="currentColor"/><circle cx="8" cy="13" r="1" fill="currentColor"/></>,
  // Nav icons
  dashboard: <><rect x="2" y="2" width="5" height="6"/><rect x="9" y="2" width="5" height="3"/><rect x="9" y="7" width="5" height="7"/><rect x="2" y="10" width="5" height="4"/></>,
  cpu: <><rect x="3.5" y="3.5" width="9" height="9" rx="1"/><rect x="6" y="6" width="4" height="4"/><path d="M6 1v2.5M10 1v2.5M6 12.5V15M10 12.5V15M1 6h2.5M1 10h2.5M12.5 6H15M12.5 10H15"/></>,
  bell2: <><path d="M3 12V7a5 5 0 0110 0v5l1 1H2l1-1z"/><path d="M6.5 13.5a1.5 1.5 0 003 0"/></>,
  workflow: <><circle cx="3" cy="3" r="1.5"/><circle cx="13" cy="3" r="1.5"/><circle cx="3" cy="13" r="1.5"/><circle cx="13" cy="13" r="1.5"/><path d="M3 4.5v7M13 4.5v7M4.5 3h7M4.5 13h7"/></>,
  form: <><rect x="3" y="2" width="10" height="12" rx="1"/><path d="M5.5 5h5M5.5 8h5M5.5 11h3"/></>,
  module: <><rect x="2" y="2" width="5.5" height="5.5"/><rect x="8.5" y="2" width="5.5" height="5.5"/><rect x="2" y="8.5" width="5.5" height="5.5"/><rect x="8.5" y="8.5" width="5.5" height="5.5"/></>,
  factory: <><path d="M2 14V7l4 2.5V7l4 2.5V5l4 9z"/><path d="M2 14h12"/></>,
  users: <><circle cx="6" cy="5" r="2.5"/><path d="M2 13c0-2.2 1.8-4 4-4s4 1.8 4 4"/><circle cx="11.5" cy="6" r="1.5" opacity="0.7"/><path d="M9 13.5c0-1.5 1-2.5 2.5-2.5s2.5 1 2.5 2.5" opacity="0.7"/></>,
  chart: <><path d="M2 13h12"/><rect x="3" y="8" width="2" height="5"/><rect x="7" y="5" width="2" height="8"/><rect x="11" y="9" width="2" height="4"/></>,
  shield: <path d="M8 1l5 2v5c0 3-2 5-5 7-3-2-5-4-5-7V3l5-2z"/>,
  // Misc
  alert: <><path d="M8 1l7 12H1L8 1z"/><path d="M8 6v3M8 11v0.5"/></>,
  alertCircle: <><circle cx="8" cy="8" r="6.5"/><path d="M8 5v3.5M8 11v0.5"/></>,
  info: <><circle cx="8" cy="8" r="6.5"/><path d="M8 7v4M8 5v0.5"/></>,
  clock: <><circle cx="8" cy="8" r="6.5"/><path d="M8 4.5V8l2 2"/></>,
  trend: <><path d="M2 11l4-4 3 3 5-5"/><path d="M9 5h5v5"/></>,
  trendDown: <><path d="M2 5l4 4 3-3 5 5"/><path d="M9 11h5v-5"/></>,
  pause: <><rect x="4" y="3" width="3" height="10" rx="1"/><rect x="9" y="3" width="3" height="10" rx="1"/></>,
  play: <path d="M5 3l8 5-8 5V3z"/>,
  drag: <><circle cx="6" cy="4" r="0.8" fill="currentColor"/><circle cx="10" cy="4" r="0.8" fill="currentColor"/><circle cx="6" cy="8" r="0.8" fill="currentColor"/><circle cx="10" cy="8" r="0.8" fill="currentColor"/><circle cx="6" cy="12" r="0.8" fill="currentColor"/><circle cx="10" cy="12" r="0.8" fill="currentColor"/></>,
  link: <><path d="M7 9l-2 2a2 2 0 11-3-3l2-2M9 7l2-2a2 2 0 113 3l-2 2M6 10l4-4"/></>,
  database: <><ellipse cx="8" cy="3.5" rx="5.5" ry="1.5"/><path d="M2.5 3.5v9c0 1 2.5 1.5 5.5 1.5s5.5-.5 5.5-1.5v-9"/><path d="M2.5 8c0 1 2.5 1.5 5.5 1.5s5.5-.5 5.5-1.5"/></>,
  server: <><rect x="2" y="2.5" width="12" height="4.5" rx="0.5"/><rect x="2" y="9" width="12" height="4.5" rx="0.5"/><circle cx="4.5" cy="4.75" r="0.4" fill="currentColor"/><circle cx="4.5" cy="11.25" r="0.4" fill="currentColor"/></>,
  globe: <><circle cx="8" cy="8" r="6.5"/><path d="M1.5 8h13M8 1.5c2 2 3 4 3 6.5s-1 4.5-3 6.5c-2-2-3-4-3-6.5s1-4.5 3-6.5z"/></>,
  list: <><path d="M5 4h9M5 8h9M5 12h9"/><circle cx="2" cy="4" r="0.6" fill="currentColor"/><circle cx="2" cy="8" r="0.6" fill="currentColor"/><circle cx="2" cy="12" r="0.6" fill="currentColor"/></>,
  grid: <><rect x="2" y="2" width="5.5" height="5.5"/><rect x="8.5" y="2" width="5.5" height="5.5"/><rect x="2" y="8.5" width="5.5" height="5.5"/><rect x="8.5" y="8.5" width="5.5" height="5.5"/></>,
  thermometer: <><path d="M8 2.5a1.5 1.5 0 013 0v6.5a3 3 0 11-3 0V2.5z" transform="translate(-1.5 0)"/><circle cx="8" cy="11.5" r="1.5" fill="currentColor"/></>,
  power: <><path d="M5 4a4.5 4.5 0 106 0"/><path d="M8 1.5v5"/></>,
  wrench: <path d="M9 3a3 3 0 014 4l-7 7a1.5 1.5 0 11-2-2l7-7a3 3 0 00-2-2z"/>,
  zap: <path d="M9 1L3 9h4l-1 6 6-8H8l1-6z"/>,
  edit: <><path d="M11 2.5l2.5 2.5L5 13.5H2.5V11L11 2.5z"/></>,
  copy: <><rect x="5" y="5" width="9" height="9" rx="1"/><path d="M3 11V3a1 1 0 011-1h7"/></>,
  trash: <><path d="M3 4h10M5 4V2.5h6V4M4.5 4l.5 9h6l.5-9"/></>,
  arrowRight: <path d="M3 8h10M9 4l4 4-4 4"/>,
  arrowLeft: <path d="M13 8H3M7 4L3 8l4 4"/>,
  expand: <><path d="M3 6V3h3M13 10v3h-3M3 10v3h3M13 6V3h-3"/></>,
  eye: <><path d="M1 8s2.5-5 7-5 7 5 7 5-2.5 5-7 5-7-5-7-5z"/><circle cx="8" cy="8" r="2"/></>,
  shieldCheck: <><path d="M8 1l5 2v5c0 3-2 5-5 7-3-2-5-4-5-7V3l5-2z"/><path d="M5.5 8l2 2 3-4"/></>,
  branch: <><circle cx="4" cy="3" r="1.5"/><circle cx="4" cy="13" r="1.5"/><circle cx="12" cy="8" r="1.5"/><path d="M4 4.5v7M4 8h6.5"/></>,
  cloud: <path d="M5 11a3 3 0 010-6 4 4 0 017.5 1A2.5 2.5 0 0112 11H5z"/>,
};

// ============ TOAST ============
const ToastCtx = React.createContext({ push: () => {} });
const ToastHost = ({ children }) => {
  const [items, setItems] = useState([]);
  const push = useCallback((msg) => {
    const id = Date.now() + Math.random();
    setItems(s => [...s, { id, msg }]);
    setTimeout(() => setItems(s => s.filter(x => x.id !== id)), 2400);
  }, []);
  return (
    <ToastCtx.Provider value={{ push }}>
      {children}
      <div style={{ position: 'fixed', bottom: 16, right: 16, display: 'flex', flexDirection: 'column', gap: 8, zIndex: 9999 }}>
        {items.map(t => <div key={t.id} className="toast">{t.msg}</div>)}
      </div>
    </ToastCtx.Provider>
  );
};
const useToast = () => React.useContext(ToastCtx);

// ============ SPARKLINE ============
const Sparkline = ({ data, w = 80, h = 22, color = 'currentColor', fill = false, strokeWidth = 1.25 }) => {
  if (!data?.length) return null;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const step = w / (data.length - 1);
  const points = data.map((v, i) => [i * step, h - ((v - min) / range) * (h - 4) - 2]);
  const d = points.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  return (
    <svg className="spark" width={w} height={h} style={{ overflow: 'visible' }}>
      {fill && <path d={`${d} L${w},${h} L0,${h} Z`} fill={color} opacity="0.12"/>}
      <path d={d} fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinejoin="round" strokeLinecap="round"/>
    </svg>
  );
};

// Generate fake-but-coherent timeseries
const seed = (s) => {
  let x = s;
  return () => { x = (x * 9301 + 49297) % 233280; return x / 233280; };
};
const series = (n, seedNum, base = 50, vol = 10, trend = 0) => {
  const r = seed(seedNum);
  let v = base;
  return Array.from({ length: n }, (_, i) => {
    v = v + (r() - 0.5) * vol + trend;
    v = Math.max(base * 0.5, Math.min(base * 1.5, v));
    return v;
  });
};

// ============ AREA / LINE CHART ============
const LineChart = ({ data, w, h, padding = 24, color, showAxis = true, multi = null, fill = true, dashed = false }) => {
  const lines = multi || [{ data, color: color || 'var(--accent)' }];
  const all = lines.flatMap(l => l.data);
  const min = Math.min(...all);
  const max = Math.max(...all);
  const range = max - min || 1;
  const xStep = (w - padding * 2) / (lines[0].data.length - 1);

  const buildPath = (arr) => arr.map((v, i) => {
    const x = padding + i * xStep;
    const y = padding + (h - padding * 2) - ((v - min) / range) * (h - padding * 2);
    return `${i ? 'L' : 'M'}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');

  const yTicks = 4;

  return (
    <svg width={w} height={h} style={{ overflow: 'visible' }}>
      {showAxis && Array.from({ length: yTicks }).map((_, i) => {
        const y = padding + ((h - padding * 2) / (yTicks - 1)) * i;
        const val = max - (range / (yTicks - 1)) * i;
        return (
          <g key={i}>
            <line x1={padding} y1={y} x2={w - padding} y2={y} stroke="var(--line)" strokeDasharray="2 3"/>
            <text x={padding - 6} y={y + 3} fontSize="10" fill="var(--text-3)" textAnchor="end" fontFamily="JetBrains Mono">{val.toFixed(0)}</text>
          </g>
        );
      })}
      {lines.map((l, idx) => (
        <g key={idx}>
          {fill && idx === 0 && (
            <path
              d={`${buildPath(l.data)} L${w - padding},${h - padding} L${padding},${h - padding} Z`}
              fill={l.color} opacity="0.08"
            />
          )}
          <path d={buildPath(l.data)} fill="none" stroke={l.color} strokeWidth="1.5"
            strokeDasharray={l.dashed ? '3 3' : null} strokeLinejoin="round" strokeLinecap="round"/>
        </g>
      ))}
    </svg>
  );
};

// ============ BAR CHART ============
const BarChart = ({ data, w, h, padding = 24, color = 'var(--accent)' }) => {
  const max = Math.max(...data.map(d => d.value)) * 1.1;
  const bw = (w - padding * 2) / data.length;
  return (
    <svg width={w} height={h} style={{ overflow: 'visible' }}>
      {data.map((d, i) => {
        const bh = (d.value / max) * (h - padding * 2);
        const x = padding + i * bw + bw * 0.15;
        const y = h - padding - bh;
        return (
          <g key={i}>
            <rect x={x} y={y} width={bw * 0.7} height={bh} fill={d.color || color} opacity={d.muted ? 0.25 : 1} rx="1"/>
            <text x={padding + i * bw + bw * 0.5} y={h - padding + 12} fontSize="10" fill="var(--text-3)" textAnchor="middle" fontFamily="JetBrains Mono">{d.label}</text>
          </g>
        );
      })}
    </svg>
  );
};

// ============ DONUT ============
const Donut = ({ size = 140, segments, label, sub }) => {
  const total = segments.reduce((s, x) => s + x.value, 0);
  const r = size / 2 - 12;
  const c = size / 2;
  const stroke = 14;
  let acc = 0;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size}>
        <circle cx={c} cy={c} r={r} fill="none" stroke="var(--panel-3)" strokeWidth={stroke}/>
        {segments.map((s, i) => {
          const len = (s.value / total) * (Math.PI * 2 * r);
          const dash = `${len} ${Math.PI * 2 * r}`;
          const offset = -((acc / total) * (Math.PI * 2 * r));
          acc += s.value;
          return (
            <circle key={i} cx={c} cy={c} r={r} fill="none" stroke={s.color}
              strokeWidth={stroke}
              strokeDasharray={dash} strokeDashoffset={offset}
              transform={`rotate(-90 ${c} ${c})`}
              strokeLinecap="butt"/>
          );
        })}
      </svg>
      {label && (
        <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', textAlign: 'center' }}>
          <div>
            <div style={{ fontSize: 24, fontWeight: 500, letterSpacing: '-0.02em' }}>{label}</div>
            {sub && <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 2 }}>{sub}</div>}
          </div>
        </div>
      )}
    </div>
  );
};

// ============ HEATMAP ============
const Heatmap = ({ rows, cols, getVal, w, h, gap = 2, getColor }) => {
  const cw = (w - (cols - 1) * gap) / cols;
  const ch = (h - (rows - 1) * gap) / rows;
  return (
    <svg width={w} height={h}>
      {Array.from({ length: rows }).map((_, r) =>
        Array.from({ length: cols }).map((__, c) => {
          const v = getVal(r, c);
          return <rect key={`${r}-${c}`} x={c * (cw + gap)} y={r * (ch + gap)} width={cw} height={ch}
            fill={getColor(v, r, c)} rx="1.5"/>;
        })
      )}
    </svg>
  );
};

// ============ SPLIT BUTTON GROUP ============
const SegControl = ({ value, onChange, options }) => (
  <div style={{ display: 'inline-flex', background: 'var(--panel-2)', border: '1px solid var(--line)', borderRadius: 4, padding: 2 }}>
    {options.map(o => (
      <button key={o.value} onClick={() => onChange(o.value)}
        style={{
          height: 22, padding: '0 10px', border: 'none',
          background: value === o.value ? 'var(--panel)' : 'transparent',
          color: value === o.value ? 'var(--text)' : 'var(--text-2)',
          fontSize: 11, fontFamily: 'inherit', fontWeight: 500,
          borderRadius: 3, cursor: 'pointer',
          boxShadow: value === o.value ? 'var(--shadow)' : 'none'
        }}>{o.label}</button>
    ))}
  </div>
);

// Make available
Object.assign(window, {
  Icon, ICONS, ToastHost, useToast, Sparkline, LineChart, BarChart, Donut, Heatmap, SegControl, series, seed,
});
