/* global React */

/* ============================================================
   Keelway BMS — shared components & primitives
   ============================================================ */

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

/* ---------- tiny SVG icons (line, 14px) ---------- */
const Ic = {
  load: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="3" y="7" width="13" height="10" rx="1"/><path d="M16 10h4l1 3v4h-5"/><circle cx="7" cy="18" r="2"/><circle cx="17" cy="18" r="2"/></svg>,
  phone: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A15 15 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg>,
  truck: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="2" y="8" width="12" height="9" rx="1"/><path d="M14 11h5l2 3v3h-7"/><circle cx="6" cy="18" r="1.5"/><circle cx="18" cy="18" r="1.5"/></svg>,
  cash: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="3" y="6" width="18" height="12" rx="1"/><circle cx="12" cy="12" r="2.5"/><path d="M6 9v6M18 9v6"/></svg>,
  map: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/></svg>,
  portal: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="3" y="4" width="18" height="16" rx="1"/><path d="M3 9h18M8 4v16"/></svg>,
  doc: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M6 3h9l4 4v14a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/><path d="M14 3v5h5M8 13h8M8 17h5"/></svg>,
  chart: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></svg>,
  check: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M4 12l5 5L20 6"/></svg>,
  shield: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M12 3 4 6v6c0 5 3.5 8 8 9 4.5-1 8-4 8-9V6l-8-3z"/><path d="M9 12l2 2 4-4"/></svg>,
  inbox: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M3 13l3-8h12l3 8v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-6z"/><path d="M3 13h5l1 3h6l1-3h5"/></svg>,
  bot: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="4" y="8" width="16" height="12" rx="2"/><circle cx="9" cy="14" r="1"/><circle cx="15" cy="14" r="1"/><path d="M12 4v4M8 4h8"/></svg>,
  plus: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  search: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/></svg>,
  filter: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M3 5h18M6 12h12M10 19h4"/></svg>,
  arrowRight: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  more: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><circle cx="5" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/></svg>,
  play: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M6 4l14 8-14 8z"/></svg>,
  pause: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><rect x="5" y="4" width="5" height="16"/><rect x="14" y="4" width="5" height="16"/></svg>,
  spark: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M12 2v6M12 16v6M2 12h6M16 12h6M5 5l4 4M15 15l4 4M19 5l-4 4M9 15l-4 4"/></svg>,
};

/* ---------- Chip ---------- */
function Chip({ kind = "", pulse = false, children }) {
  return (
    <span className={`chip ${kind}`}>
      <span className={`dot ${pulse ? "pulse" : ""}`} />
      {children}
    </span>
  );
}

/* ---------- Sparkline ---------- */
function Sparkline({ data, w = 80, h = 24, color = "var(--accent)" }) {
  const max = Math.max(...data);
  const min = Math.min(...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 - 2) - 1}`).join(" ");
  const area = `0,${h} ${points} ${w},${h}`;
  return (
    <svg width={w} height={h} className="spark">
      <polyline fill={color} opacity="0.12" points={area} />
      <polyline fill="none" stroke={color} strokeWidth="1.2" points={points} />
    </svg>
  );
}

/* ---------- Score bar ---------- */
function ScoreBar({ value, max = 100, color }) {
  const pct = Math.max(0, Math.min(100, (value / max) * 100));
  return (
    <div className="score-bar">
      <div className="track">
        <div className="fill" style={{ width: `${pct}%`, background: color || "var(--accent)" }} />
      </div>
      <span className="num">{value}</span>
    </div>
  );
}

/* ---------- Waveform ---------- */
function Waveform({ bars = 40, active = true, seed = 1 }) {
  const heights = useMemo(() => {
    const out = [];
    let s = seed * 9301;
    for (let i = 0; i < bars; i++) {
      s = (s * 9301 + 49297) % 233280;
      out.push(4 + (s / 233280) * 18);
    }
    return out;
  }, [bars, seed]);
  const [tick, setTick] = useState(0);
  useEffect(() => {
    if (!active) return;
    const id = setInterval(() => setTick((t) => t + 1), 180);
    return () => clearInterval(id);
  }, [active]);
  return (
    <div className="wave">
      {heights.map((h, i) => {
        const phase = active ? (Math.sin((tick + i) * 0.5) + 1) / 2 : 0.5;
        return <span key={i} className="bar" style={{ height: `${h * (0.6 + phase * 0.6)}px`, opacity: active ? 1 : 0.45 }} />;
      })}
    </div>
  );
}

/* ---------- Avatar + group ---------- */
function Av({ name, color }) {
  const initials = name.split(" ").map(s => s[0]).join("").slice(0, 2).toUpperCase();
  const hueSeed = name.split("").reduce((a, c) => a + c.charCodeAt(0), 0);
  const hue = color || `hsl(${hueSeed % 360}, 30%, 35%)`;
  return <span className="av" style={{ background: hue }}>{initials}</span>;
}
function AvGroup({ names }) {
  return (
    <span className="av-group">
      {names.map((n, i) => <Av key={i} name={n} />)}
    </span>
  );
}

/* ---------- KPI ---------- */
function KPI({ label, value, delta, deltaKind = "up", spark }) {
  return (
    <div className="kpi">
      <div className="kpi-label">{label}</div>
      <div className="kpi-val">{value}</div>
      {delta && (
        <div className={`kpi-delta ${deltaKind}`}>
          <span style={{ color: deltaKind === "up" ? "var(--ok)" : "var(--danger)" }}>
            {deltaKind === "up" ? "▲" : "▼"} {delta}
          </span>
          <span className="dim">vs last wk</span>
        </div>
      )}
      {spark && <div className="spark"><Sparkline data={spark} w={70} h={20} /></div>}
    </div>
  );
}

/* ---------- Panel wrapper ---------- */
function Panel({ title, actions, children, flush, style, className = "" }) {
  return (
    <div className={`panel ${className}`} style={style}>
      {title && (
        <div className="panel-head">
          <div className="panel-title">{title}</div>
          {actions && <div className="panel-actions">{actions}</div>}
        </div>
      )}
      <div className={`panel-body ${flush ? "flush" : ""}`}>{children}</div>
    </div>
  );
}

/* ---------- Loading shimmer rows ---------- */
function ShimmerRow() {
  return <div style={{ height: 14, background: "linear-gradient(90deg, var(--bg-2), var(--bg-3), var(--bg-2))", backgroundSize: "200% 100%", animation: "load 1.4s infinite", borderRadius: 3 }} />;
}

/* ---------- AiBand: agentic suggestion strip ---------- */
function AiBand({ text, actions, confidence }) {
  return (
    <div className="ai-band">
      <span className="ai-tag">AI</span>
      <span style={{ flex: 1 }}>{text}</span>
      {confidence != null && (
        <span className="mono dim" style={{ fontSize: 10 }}>conf {confidence}%</span>
      )}
      <div style={{ display: "flex", gap: 6 }}>{actions}</div>
    </div>
  );
}

/* ---------- export all to window ---------- */
Object.assign(window, {
  Ic, Chip, Sparkline, ScoreBar, Waveform, Av, AvGroup, KPI, Panel, ShimmerRow, AiBand,
});
