/* ui.jsx — Van Haren Learning design primitives */
const { useState, useEffect, useRef, useMemo, createElement } = React;

/* ----------------------------------------------------------
   ICONS — stroke-based, inherit currentColor. No emoji.
   ---------------------------------------------------------- */
const P = (d, o) => ({ d, ...(o || {}) });
const ICONS = {
  grid: ["M4 4h7v7H4zM13 4h7v7h-7zM13 13h7v7h-7zM4 13h7v7H4z"],
  stack: ["M12 3l9 5-9 5-9-5 9-5z", "M3 13l9 5 9-5", "M3 17l9 5 9-5"],
  passport: ["M5 3h11l3 3v15H5z", "M9 8h6", "M9 12h6", "M9 16h3"],
  book: ["M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2z", "M19 19H6a2 2 0 0 0-2 2"],
  trophy: ["M7 4h10v4a5 5 0 0 1-10 0z", "M7 6H4v2a3 3 0 0 0 3 3", "M17 6h3v2a3 3 0 0 1-3 3", "M10 14h4l-.5 4h-3z", "M8 21h8"],
  search: ["M11 11m-7 0a7 7 0 1 0 14 0a7 7 0 1 0-14 0", "M21 21l-4.3-4.3"],
  bell: ["M6 9a6 6 0 1 1 12 0c0 5 2 6 2 6H4s2-1 2-6", "M10 20a2 2 0 0 0 4 0"],
  gear: ["M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z", "M19.4 15a1.6 1.6 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.6 1.6 0 0 0-2.7 1.1V21a2 2 0 1 1-4 0v-.1A1.6 1.6 0 0 0 6.6 19l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1A1.6 1.6 0 0 0 4 13.6H4a2 2 0 1 1 0-4h.1A1.6 1.6 0 0 0 5 6.6L4.9 6.5a2 2 0 1 1 2.8-2.8l.1.1A1.6 1.6 0 0 0 10 4.6V4a2 2 0 1 1 4 0v.1a1.6 1.6 0 0 0 2.7 1.1l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0-.3 1.8"],
  chevR: ["M9 6l6 6-6 6"],
  chevL: ["M15 6l-6 6 6 6"],
  chevD: ["M6 9l6 6 6-6"],
  arrowR: ["M5 12h14", "M13 6l6 6-6 6"],
  play: [["M7 5l12 7-12 7z", { fill: "currentColor", stroke: "none" }]],
  pause: [["M8 5h3v14H8z", { fill: "currentColor", stroke: "none" }], ["M14 5h3v14h-3z", { fill: "currentColor", stroke: "none" }]],
  check: ["M5 13l4 4L19 7"],
  checkCircle: ["M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20z", "M8 12l3 3 5-6"],
  star: [["M12 3l2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 18l-5.8 3 1.1-6.5L2.6 9.8l6.5-.9z", { fill: "currentColor", stroke: "none" }]],
  flame: ["M12 3c1 3-2 4-2 7a2 2 0 0 0 4 0c2 2 3 3 3 6a5 5 0 0 1-10 0c0-4 4-5 5-13z"],
  lock: ["M6 11h12v9H6z", "M9 11V8a3 3 0 0 1 6 0v3"],
  wand: ["M15 4V2M15 10V8M19 6h2M9 6h2", "M17 6l-12 12", "M14 9l1 1"],
  sparkle: [["M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z", { fill: "currentColor", stroke: "none" }]],
  plus: ["M12 5v14", "M5 12h14"],
  download: ["M12 4v11", "M8 11l4 4 4-4", "M5 20h14"],
  share: ["M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7", "M12 3v13", "M8 7l4-4 4 4"],
  qr: ["M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4z", "M14 14h2v2h-2zM18 14h2v2h-2zM14 18h2v2h-2zM18 18h2v2h-2z"],
  volume: ["M4 9v6h4l5 4V5L8 9z", "M16 9a3 3 0 0 1 0 6", "M18.5 7a6 6 0 0 1 0 10"],
  volumeOn: ["M4 9v6h4l5 4V5L8 9z", "M16 9a3 3 0 0 1 0 6"],
  highlight: ["M9 14l-3 3v3h3l3-3", "M9 14l8-8 4 4-8 8", "M13 6l4 4"],
  note: ["M5 4h14v12l-5 5H5z", "M14 21v-5h5"],
  target: ["M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0-18 0", "M12 12m-5 0a5 5 0 1 0 10 0a5 5 0 1 0-10 0", "M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0"],
  bars: ["M4 20V10M10 20V4M16 20v-7M22 20H2"],
  dice: ["M4 4h16v16H4z", "M8.5 8.5h.01M15.5 8.5h.01M12 12h.01M8.5 15.5h.01M15.5 15.5h.01"],
  cert: ["M12 14a5 5 0 1 0 0-10 5 5 0 0 0 0 10z", "M9 13l-2 7 5-3 5 3-2-7"],
  users: ["M16 19v-1a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v1", "M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z", "M22 19v-1a4 4 0 0 0-3-3.9", "M16 3.1A4 4 0 0 1 16 11"],
  clock: ["M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0-18 0", "M12 7v5l3 2"],
  bolt: [["M13 2L4 14h6l-1 8 9-12h-6z", { fill: "currentColor", stroke: "none" }]],
  x: ["M6 6l12 12M18 6L6 18"],
  pptx: ["M5 3h14v18H5z", "M9 8h4a2.5 2.5 0 0 1 0 5H9zM9 13v4"],
  layers: ["M12 3l9 5-9 5-9-5z", "M3 12l9 5 9-5"],
  globe: ["M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0-18 0", "M3 12h18", "M12 3a14 14 0 0 1 0 18a14 14 0 0 1 0-18z"],
  shield: ["M12 3l8 3v6c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V6z"],
  medal: ["M8 3l4 7 4-7", "M12 21a5 5 0 1 0 0-10 5 5 0 0 0 0 10z", "M12 14.5l1.2 2.4 2.6.3-1.9 1.8.5 2.6-2.4-1.3-2.4 1.3.5-2.6-1.9-1.8 2.6-.3z"],
  graduation: ["M3 9l9-5 9 5-9 5z", "M7 11v5c0 1 2.2 2.5 5 2.5s5-1.5 5-2.5v-5", "M21 9v5"],
  rocket: ["M5 15c-1 1-1 4-1 4s3 0 4-1", "M9 12a8 8 0 0 1 9-9 8 8 0 0 1-9 9z", "M9 12l3 3", "M15 9m-1 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0"],
  brain: ["M9 3a3 3 0 0 0-3 3 3 3 0 0 0-2 5 3 3 0 0 0 2 5 3 3 0 0 0 6 0V4a3 3 0 0 0-3-1z", "M15 3a3 3 0 0 1 3 3 3 3 0 0 1 2 5 3 3 0 0 1-2 5 3 3 0 0 1-6 0"],
  pen: ["M4 20l4-1L20 7l-3-3L5 16z", "M14 6l3 3"],
  list: ["M8 6h13M8 12h13M8 18h13", "M3 6h.01M3 12h.01M3 18h.01"],
  filter: ["M3 5h18l-7 8v6l-4-2v-4z"],
  link: ["M9 15l6-6", "M11 6l1-1a4 4 0 0 1 6 6l-1 1", "M13 18l-1 1a4 4 0 0 1-6-6l1-1"],
  eu: ["M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0-18 0", "M12 6v1M12 17v1M6 12h1M17 12h1M8 8l.7.7M15.3 15.3l.7.7M16 8l-.7.7M8.7 15.3l-.7.7"],
  heart: [["M12 21C5 16 3 12 3 8.5A4.5 4.5 0 0 1 12 6a4.5 4.5 0 0 1 9 2.5C21 12 19 16 12 21z", { fill: "currentColor", stroke: "none" }]],
  refresh: ["M3 12a9 9 0 0 1 15-6.7L21 8", "M21 3v5h-5", "M21 12a9 9 0 0 1-15 6.7L3 16", "M3 21v-5h5"],
  flag: ["M5 21V4M5 4h11l-2 4 2 4H5"],
};

function Icon({ name, size = 22, stroke = 2, style, className }) {
  const paths = ICONS[name] || ICONS.grid;
  return createElement("svg", {
    width: size, height: size, viewBox: "0 0 24 24", fill: "none",
    stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round",
    strokeLinejoin: "round", style, className, "aria-hidden": true,
  }, paths.map((p, i) => {
    if (Array.isArray(p)) return createElement("path", { key: i, d: p[0], ...p[1] });
    return createElement("path", { key: i, d: p });
  }));
}

/* ----------------------------------------------------------
   Logo
   ---------------------------------------------------------- */
function Logo({ height = 30, white = false }) {
  return createElement("img", {
    src: white ? "assets/vanharen-logo-white.png" : "assets/vanharen-logo.png",
    alt: "Van Haren", style: { height, width: "auto", display: "block" },
  });
}

/* hexagon mark only (CSS) */
function HexMark({ size = 34 }) {
  return (
    <div style={{ width: size, height: size, position: "relative", flex: "none" }}>
      <div className="hex-flat" style={{ position: "absolute", inset: 0, background: "var(--vh-blue-500)",
        clipPath: "polygon(50% 0,93% 25%,93% 75%,50% 100%,7% 75%,7% 25%)" }} />
      <svg viewBox="0 0 24 24" width={size} height={size} style={{ position: "absolute", inset: 0 }}>
        {/* graduation cap — signifies a learner */}
        <path d="M12 5.2 L21 9 L12 12.8 L3 9 Z" fill="#fff" />
        <path d="M6.6 10.5 V13.9 C6.6 15.4 9 16.4 12 16.4 C15 16.4 17.4 15.4 17.4 13.9 V10.5" stroke="#fff" strokeWidth="1.7" fill="none" strokeLinejoin="round" strokeLinecap="round" />
        <path d="M21 9 V13.2" stroke="#fff" strokeWidth="1.5" strokeLinecap="round" />
        <circle cx="21" cy="13.9" r="1" fill="#fff" />
      </svg>
    </div>
  );
}

/* ----------------------------------------------------------
   Badge — respects badgeStyle tweak ('hex' | 'shield' | 'circle')
   ---------------------------------------------------------- */
const CLIP = {
  hex: "polygon(50% 0,93% 25%,93% 75%,50% 100%,7% 75%,7% 25%)",
  shield: "polygon(50% 0,100% 14%,100% 60%,50% 100%,0 60%,0 14%)",
  circle: "circle(50%)",
};
function Badge({ icon = "star", size = 64, color = "var(--accent)", ink = "#231f20",
                 locked = false, style = "hex", ring = true, glyphSize }) {
  const clip = CLIP[style] || CLIP.hex;
  const bg = locked ? "var(--surface-3)" : color;
  return (
    <div style={{ width: size, height: size, position: "relative", flex: "none" }}>
      {ring && !locked && (
        <div style={{ position: "absolute", inset: -4, clipPath: clip,
          background: `color-mix(in oklab, ${color}, transparent 70%)` }} />
      )}
      <div style={{ position: "absolute", inset: 0, clipPath: clip, background: bg,
        display: "grid", placeItems: "center",
        boxShadow: locked ? "none" : "inset 0 -6px 12px rgba(0,0,0,.12)" }}>
        <Icon name={locked ? "lock" : icon} size={glyphSize || size * 0.42}
          style={{ color: locked ? "var(--ink-3)" : ink }} stroke={2.2} />
      </div>
    </div>
  );
}

/* ----------------------------------------------------------
   ProgressRing
   ---------------------------------------------------------- */
function Ring({ value = 0, size = 56, stroke = 6, color = "var(--vh-blue-500)", track = "var(--surface-3)", children, label }) {
  const r = (size - stroke) / 2, c = 2 * Math.PI * r, off = c * (1 - value / 100);
  return (
    <div style={{ position: "relative", width: size, height: size, display: "grid", placeItems: "center" }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <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}
          strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"
          style={{ transition: "stroke-dashoffset .8s cubic-bezier(.2,.7,.3,1)" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        {children || <span style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: size * 0.28 }}>{Math.round(value)}<span style={{ fontSize: size * 0.16 }}>%</span></span>}
      </div>
      {label && <span className="dim" style={{ position: "absolute", bottom: -18, fontSize: 11 }}>{label}</span>}
    </div>
  );
}

/* striped image placeholder */
function Placeholder({ label, h = 160, style }) {
  return (
    <div className="ph" style={{ height: h, borderRadius: "var(--r-md)", ...style }}>
      <span className="lbl">{label}</span>
    </div>
  );
}

/* small XP/points pill that respects pointsStyle tweak */
function Points({ value, pointsStyle = "solid", icon = "bolt", size = "md" }) {
  const pad = size === "sm" ? "5px 10px 5px 8px" : "7px 12px 7px 9px";
  const fs = size === "sm" ? 13 : 14.5;
  const styles = pointsStyle === "soft"
    ? { background: "var(--accent-soft)", color: "var(--accent-ink)" }
    : pointsStyle === "outline"
      ? { background: "transparent", color: "var(--ink)", border: "1.5px solid var(--accent)" }
      : { background: "var(--accent)", color: "#231f20" };
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: pad, borderRadius: 999, fontWeight: 800, fontFamily: "var(--display)", fontSize: fs, ...styles }}>
      <Icon name={icon} size={fs + 2} />{typeof value === "number" ? value.toLocaleString() : value}
    </span>
  );
}

function Toast({ icon = "checkCircle", children, onDone, ms = 2200 }) {
  useEffect(() => { const t = setTimeout(onDone, ms); return () => clearTimeout(t); }, []);
  return <div className="toast"><Icon name={icon} size={20} style={{ color: "var(--vh-teal)" }} />{children}</div>;
}

Object.assign(window, { Icon, ICONS, Logo, HexMark, Badge, Ring, Placeholder, Points, Toast, CLIP });
