// components.jsx — shared UI building blocks

// ── Icons (12-16px line icons) ─────────────────────────────────────
const Icon = ({ d, size = 14, fill, stroke = "currentColor", sw = 1.6, ...rest }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} className="ico"
       fill={fill || "none"} stroke={fill ? "none" : stroke}
       strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" {...rest}>
    {typeof d === 'string' ? <path d={d} /> : d}
  </svg>
);

const I = {
  dash:   <Icon d="M3 13h8V3H3zM13 21h8V11h-8zM3 21h8v-6H3zM13 9h8V3h-8z" />,
  term:   <Icon d="M4 6l4 6-4 6M11 18h9" />,
  logs:   <Icon d="M4 6h16M4 12h10M4 18h16M19 12l2 2-2 2" />,
  users:  <Icon d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" />,
  map:    <Icon d="M9 4l-6 2v14l6-2 6 2 6-2V4l-6 2-6-2zM9 4v14M15 6v14" />,
  sliders:<Icon d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6" />,
  code:   <Icon d="M16 18l6-6-6-6M8 6l-6 6 6 6M14 4l-4 16" />,
  plug:   <Icon d="M9 2v6M15 2v6M5 8h14v3a7 7 0 0 1-14 0V8zM12 18v4" />,
  clock:  <Icon d="M12 6v6l4 2" sw={1.6} />,
  shield: <Icon d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />,
  search: <Icon d="M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM21 21l-4.3-4.3" sw={1.8} />,
  chev:   <Icon d="M6 9l6 6 6-6" sw={1.8} />,
  plus:   <Icon d="M12 5v14M5 12h14" />,
  x:      <Icon d="M6 6l12 12M18 6L6 18" />,
  trash:  <Icon d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />,
  pause:  <Icon d="M6 4h4v16H6zM14 4h4v16h-4z" />,
  play:   <Icon d="M5 3l16 9-16 9z" fill="currentColor" />,
  reload: <Icon d="M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5" />,
  power:  <Icon d="M18.36 6.64a9 9 0 1 1-12.73 0M12 2v10" />,
  lock:   <Icon d="M5 11h14v10H5zM8 11V7a4 4 0 0 1 8 0v4" />,
  unlock: <Icon d="M5 11h14v10H5zM8 11V7a4 4 0 0 1 7.5-2" />,
  upload: <Icon d="M12 3v14M5 10l7-7 7 7M3 21h18" />,
  download: <Icon d="M12 3v14M5 12l7 7 7-7M3 21h18" />,
  out:    <Icon d="M15 3h6v6M10 14L21 3M21 14v7H3V3h7" />,
  git:    <Icon d="M12 2A10 10 0 0 0 8.84 21.5c.5.09.66-.22.66-.48v-1.7c-2.78.6-3.36-1.34-3.36-1.34-.46-1.17-1.11-1.48-1.11-1.48-.91-.62.07-.6.07-.6 1 .07 1.53 1.04 1.53 1.04.89 1.52 2.34 1.08 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.1.39-2 1.03-2.7-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02a9.6 9.6 0 0 1 5 0c1.91-1.29 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.6 1.03 2.7 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.85V21c0 .27.16.58.67.48A10 10 0 0 0 12 2z" />,
  user:   <Icon d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" />,
  check:  <Icon d="M5 13l4 4L19 7" sw={2} />,
  alert:  <Icon d="M12 9v4M12 17h.01M10.3 3.86l-8.18 14.16A2 2 0 0 0 3.84 21h16.32a2 2 0 0 0 1.72-2.98L13.7 3.86a2 2 0 0 0-3.4 0z" />,
  flag:   <Icon d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22V15" />,
  cpu:    <Icon d="M4 4h16v16H4zM9 9h6v6H9zM4 9h1M4 15h1M19 9h1M19 15h1M9 4v1M15 4v1M9 19v1M15 19v1" />,
  ram:    <Icon d="M3 8h18v9H3zM7 12v2M11 12v2M15 12v2M19 12v2M5 19v1M9 19v1M13 19v1M17 19v1M19 19v1" />,
  pulse:  <Icon d="M3 12h4l3-9 4 18 3-9h4" />,
  bolt:   <Icon d="M13 2L3 14h8l-1 8 11-13h-9z" />,
  folder: <Icon d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />,
  file:   <Icon d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6" />,
  star:   <Icon d="M12 2l3 7 7 .5-5.5 4.5L18 22l-6-4-6 4 1.5-8L2 9.5 9 9z" />,
  caret:  <Icon d="M9 6l6 6-6 6" />,
  more:   <Icon d="M5 12h.01M12 12h.01M19 12h.01" sw={3} />,
  cog:    <Icon d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9 1.65 1.65 0 0 0 4.27 7.18l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9A1.65 1.65 0 0 0 10 3.09V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9c.36.16.71.23 1 .51L21 9a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />,
  filter: <Icon d="M22 3H2l8 9.5V19l4 2v-8.5z" />,
  sun:    <Icon d="M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10zM12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />,
  link:   <Icon d="M10 13a5 5 0 0 0 7.5 5l3-3a5 5 0 0 0-7-7l-1 1M14 11a5 5 0 0 0-7.5-5l-3 3a5 5 0 0 0 7 7l1-1" />,
  copy:   <Icon d="M9 9h12v12H9zM5 15H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v2" />,
  workshop: <Icon d="M4 4h16v6H4zM4 14h16v6H4zM7 7h.01M7 17h.01" />,
};

// ── Flag — text-rendered, mono ─────────────────────────────────────
const FLAG_BG = {
  SE: 'linear-gradient(180deg,#005d9e 0 41%,#fecb00 41% 59%,#005d9e 59%)',
  DE: 'linear-gradient(180deg,#000 0 33%,#d00 33% 66%,#fc0 66%)',
  PL: 'linear-gradient(180deg,#fff 0 50%,#dc143c 50%)',
  JP: 'radial-gradient(circle at 50% 50%,#bc002d 0 28%,#fff 28%)',
  FR: 'linear-gradient(90deg,#002395 0 33%,#fff 33% 66%,#ed2939 66%)',
  LT: 'linear-gradient(180deg,#fdb913 0 33%,#006a44 33% 66%,#c1272d 66%)',
  FI: 'linear-gradient(180deg,#fff 40%,#003580 40% 60%,#fff 60%),linear-gradient(90deg,#fff 30%,#003580 30% 42%,#fff 42%)',
  BR: 'radial-gradient(ellipse at 50% 50%,#ffdf00 0 50%,#009c3b 50%)',
  US: 'linear-gradient(180deg,#bf0a30 0 14%,#fff 14% 28%,#bf0a30 28% 42%,#fff 42% 56%,#bf0a30 56% 70%,#fff 70% 84%,#bf0a30 84%)',
  GB: 'linear-gradient(45deg,#012169 0 40%,#fff 40% 60%,#012169 60%)',
};
const Flag = ({ c }) => (
  <i className="flag" title={c} style={{ background: FLAG_BG[c] || 'var(--bg-4)' }} />
);

// ── Sparkline ──────────────────────────────────────────────────────
function Spark({ data, color = "currentColor", fill = true, height = 32, w = 200 }) {
  const max = Math.max(...data), min = Math.min(...data);
  const rng = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = height - ((v - min) / rng) * (height - 4) - 2;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  });
  const dLine = `M ${pts.join(' L ')}`;
  const dArea = `${dLine} L ${w},${height} L 0,${height} Z`;
  const gid = React.useId();
  return (
    <svg className="spark" viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none">
      {fill && (
        <>
          <defs>
            <linearGradient id={gid} x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor={color} stopOpacity="0.35" />
              <stop offset="100%" stopColor={color} stopOpacity="0" />
            </linearGradient>
          </defs>
          <path d={dArea} fill={`url(#${gid})`} />
        </>
      )}
      <path d={dLine} fill="none" stroke={color} strokeWidth="1.4" strokeLinejoin="round" />
    </svg>
  );
}

// ── Map thumb (procedural placeholder; varies per map) ─────────────
function MapThumb({ id }) {
  // Deterministic pseudo "radar" pattern keyed off the map id.
  const seed = [...id].reduce((a, c) => a + c.charCodeAt(0), 0);
  const rand = (n) => ((seed * (n + 1) * 9301 + 49297) % 233280) / 233280;
  const tone = id.startsWith('de_') ? '#3a342a' : id.startsWith('cs_') ? '#2c2e3a' : '#2a3a32';
  const rects = Array.from({ length: 9 }, (_, i) => ({
    x: 8 + rand(i) * 60, y: 6 + rand(i + 9) * 40,
    w: 12 + rand(i + 18) * 30, h: 8 + rand(i + 27) * 22,
    r: rand(i + 36) > 0.6 ? 2 : 0,
    o: 0.16 + rand(i + 45) * 0.35,
  }));
  const lines = Array.from({ length: 4 }, (_, i) => ({
    x1: 4 + rand(i + 60) * 90, y1: 4 + rand(i + 65) * 50,
    x2: 4 + rand(i + 70) * 90, y2: 4 + rand(i + 75) * 50,
  }));
  return (
    <svg viewBox="0 0 100 60" preserveAspectRatio="xMidYMid slice">
      <rect width="100" height="60" fill={tone} />
      <pattern id={`g-${id}`} width="6" height="6" patternUnits="userSpaceOnUse">
        <path d="M6 0H0v6" fill="none" stroke="rgba(255,255,255,.04)" strokeWidth=".5" />
      </pattern>
      <rect width="100" height="60" fill={`url(#g-${id})`} />
      {rects.map((r, i) => (
        <rect key={i} x={r.x} y={r.y} width={r.w} height={r.h} rx={r.r}
              fill="rgba(255,255,255,.08)" stroke="rgba(255,255,255,.18)" strokeWidth=".4"
              opacity={r.o} />
      ))}
      {lines.map((l, i) => (
        <line key={i} {...l} stroke="rgba(255,255,255,.12)" strokeWidth=".6" />
      ))}
      {/* bombsites */}
      <text x="20" y="32" fill="rgba(220,80,40,.55)" fontSize="6" fontFamily="ui-monospace,monospace" fontWeight="700">A</text>
      <text x="74" y="40" fill="rgba(220,80,40,.55)" fontSize="6" fontFamily="ui-monospace,monospace" fontWeight="700">B</text>
    </svg>
  );
}

// ── Server switcher dropdown ───────────────────────────────────────
function ServerSwitcher({ current, servers, onPick, onRemove, onAdd }) {
  const [open, setOpen] = React.useState(false);
  const [form, setForm] = React.useState({ name: '', addr: '', pass: '' });
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);
  const cur = servers.find((s) => s.id === current) || servers[0];
  return (
    <div ref={ref} className="srv-wrap" style={{ position: 'relative' }}>
      <button className="srv" onClick={() => setOpen(!open)}>
        <span className={"dot " + (cur.status === 'offline' ? 'off' : cur.status === 'warn' ? 'warn' : '')} />
        <span className="lbl">{cur.name}</span>
        <span className="meta">{cur.addr}</span>
        <span className="chev">{I.chev}</span>
      </button>
      {open && (
        <div className="srv-pop">
          <div className="sec">Servers</div>
          {servers.map((s) => (
            <div key={s.id} className={"srv-row " + (s.id === current ? 'active' : '')}
                 onClick={() => { onPick(s.id); setOpen(false); }}>
              <span className={"dot " + (s.status === 'offline' ? 'off' : s.status === 'warn' ? 'warn' : '')} />
              <div>
                <div className="name">{s.name}</div>
                <div className="addr">{s.addr} · {s.region}</div>
              </div>
              <div className="addr">{s.players}</div>
              <button className="x" onClick={(e) => { e.stopPropagation(); onRemove(s.id); }} title="Remove">{I.x}</button>
            </div>
          ))}
          <div className="sec">Add server</div>
          <div className="add-form">
            <input placeholder="name"  value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} />
            <input placeholder="ip:port"  value={form.addr} onChange={(e) => setForm({ ...form, addr: e.target.value })} />
            <button onClick={() => { onAdd(form); setForm({ name: '', addr: '', pass: '' }); }}>Add</button>
          </div>
          <div className="add-form" style={{ gridTemplateColumns: '1fr', paddingTop: 0, borderTop: 0, marginTop: -4 }}>
            <input placeholder="rcon password" type="password" value={form.pass}
                   onChange={(e) => setForm({ ...form, pass: e.target.value })} />
          </div>
        </div>
      )}
    </div>
  );
}

// ── Compact components ─────────────────────────────────────────────
const Stat = ({ label, value, unit, delta, foot, color }) => (
  <div className="stat">
    <div className="lbl">{label}</div>
    <div className="v" style={color ? { color } : null}>
      <span>{value}</span>
      {unit && <span className="u">{unit}</span>}
      {delta && <span className={"delta" + (String(delta).startsWith('-') ? ' bad' : '')}>{delta}</span>}
    </div>
    {foot && <div className="foot">{foot}</div>}
  </div>
);

const SectionTitle = ({ children, right }) => (
  <div className="div-lbl" style={{ marginTop: 8 }}>
    <span>{children}</span>
    {right && <span style={{ flex: 'none' }}>{right}</span>}
  </div>
);

// flag toggle pill
const Pill = ({ on, children, onClick, color }) => (
  <button className={"chip " + (on ? 'on' : '')} onClick={onClick}
          style={color && on ? { color, borderColor: color + '55' } : null}>
    {children}
  </button>
);

// ── Generic Sparkline for dashboard ────────────────────────────────
function genSeries(seed, n = 36, base = 10, amp = 4) {
  const out = [];
  let v = base;
  for (let i = 0; i < n; i++) {
    seed = (seed * 9301 + 49297) % 233280;
    v += (seed / 233280 - 0.5) * amp;
    v = Math.max(0, v);
    out.push(v);
  }
  return out;
}

Object.assign(window, {
  Icon, I, Flag, Spark, MapThumb, ServerSwitcher,
  Stat, SectionTitle, Pill, genSeries,
});
