/* Shared UI primitives — Icon set (Lucide-style, stroke 1.75) + helpers.
 * Exposes Icon, Badge, fmtEUR, routeChip helpers on window.
 */

const ICONS = {
  dashboard: "M3 3h7v9H3zM14 3h7v5h-7zM14 12h7v9h-7zM3 16h7v5H3z",
  folder: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
  database: "M12 3c4.4 0 8 1.3 8 3s-3.6 3-8 3-8-1.3-8-3 3.6-3 8-3zM4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3",
  cloud: "M17.5 19H7a5 5 0 1 1 .8-9.9A6.5 6.5 0 0 1 20 12a3.5 3.5 0 0 1-2.5 7z",
  layers: "M12 3 3 8l9 5 9-5zM3 13l9 5 9-5M3 18l9 5 9-5",
  settings: "M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6zM19.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 0 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 12.6H4a2 2 0 0 1 0-4h.1A1.6 1.6 0 0 0 5 5.6l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.6 1.6 0 0 0 2.7-1.1V2a2 2 0 0 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",
  search: "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM21 21l-4.3-4.3",
  bell: "M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 0 1-3.4 0",
  fileText: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8zM14 3v5h5M9 13h6M9 17h6",
  fileCheck: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8zM14 3v5h5M9 15l2 2 4-4",
  check: "M20 6 9 17l-5-5",
  checkCircle: "M22 11.1V12a10 10 0 1 1-5.9-9.1M22 4 12 14.01l-3-3",
  alert: "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0zM12 9v4M12 17h.01",
  xCircle: "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM15 9l-6 6M9 9l6 6",
  clock: "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 6v6l4 2",
  mapPin: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0zM12 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z",
  building: "M3 21h18M5 21V5a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v16M19 21v-8a2 2 0 0 0-2-2h-2M9 7h2M9 11h2M9 15h2",
  user: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",
  chevronRight: "M9 18l6-6-6-6",
  arrowRight: "M5 12h14M13 5l7 7-7 7",
  plus: "M12 5v14M5 12h14",
  download: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3",
  upload: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12",
  shield: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",
  route: "M6 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM18 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h0",
  coins: "M9 14a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM15.5 9.5A6 6 0 1 1 8 21M7 6h1v4M16.7 14H18v4",
  gavel: "M14 13l-7.5 7.5a2.1 2.1 0 0 1-3-3L11 10M16 16l4-4M9 7l4 4M17.5 4.5l2 2M4 21h8",
  package: "M21 16V8a2 2 0 0 0-1-1.7l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.7l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zM3.3 7 12 12l8.7-5M12 22V12",
  history: "M3 3v5h5M3.05 13A9 9 0 1 0 6 5.3L3 8M12 7v5l4 2",
  eye: "M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",
  lock: "M19 11H5a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zM7 11V7a5 5 0 0 1 10 0v4",
  link: "M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1.5 1.5M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1.5-1.5",
  inbox: "M22 12h-6l-2 3h-4l-2-3H2M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.5-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1z",
  flag: "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 22v-7",
  calendar: "M8 2v4M16 2v4M3 10h18M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",
  filter: "M22 3H2l8 9.5V19l4 2v-8.5z",
  dot: "M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0-6 0",
  refresh: "M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5",
};

function Icon({ name, size = 18, stroke = 1.75, fill = false, style, className }) {
  const d = ICONS[name];
  if (!d) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? "currentColor" : "none"}
         stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
         className={(className ? className + " " : "") + "ico"} style={style} aria-hidden="true">
      <path d={d} />
    </svg>
  );
}

function fmtEUR(n) {
  const neg = n < 0;
  const s = "€ " + Math.abs(n).toLocaleString("nl-NL");
  return neg ? "− " + s : s;
}

// Status → badge tone + label maps
const ROUTE_STATUS = {
  mogelijk:  { tone: "ok",      label: "Mogelijk" },
  controle:  { tone: "warn",    label: "Controle nodig" },
  niet:      { tone: "err",     label: "Niet mogelijk" },
  lokaal:    { tone: "info",    label: "Lokaal afhankelijk" },
  buiten:    { tone: "neutral", label: "Buiten MVP" },
};
const DOC_STATUS = {
  ok:      { tone: "ok",      label: "Akkoord",  icon: "fileCheck" },
  review:  { tone: "warn",    label: "Onduidelijk", icon: "fileText" },
  missing: { tone: "err",     label: "Ontbreekt", icon: "fileText" },
  expired: { tone: "warn",    label: "Verlopen", icon: "clock" },
  rejected:{ tone: "err",     label: "Afgekeurd", icon: "xCircle" },
};

function Badge({ tone = "neutral", children, dot = false, sm = false }) {
  return (
    <span className={"badge " + tone + (sm ? " sm" : "")}>
      {dot && <span className="dot"></span>}{children}
    </span>
  );
}

function Conf({ value }) {
  if (value == null) return <span className="conf"><span className="muted">geen bron</span></span>;
  const pct = Math.round(value * 100);
  const low = value < 0.75;
  return (
    <span className={"conf" + (low ? " low" : "")}>
      <span className="bar"><i style={{ width: pct + "%" }}></i></span>{pct}%
    </span>
  );
}

function Logo({ size = 32, radius = 0 }) {
  const E = "#01C38D", INK = "#191E29", W = "#fff";
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" aria-hidden="true" style={{ display: "block", flex: "0 0 auto" }}>
      <rect width="100" height="100" rx={radius} fill={INK} />
      <rect x="21" y="71" width="58" height="5" fill={W} />
      <rect x="25" y="50" width="14" height="21" fill={W} />
      <polygon points="43,71 43,40 57,33 57,71" fill={W} />
      <polygon points="61,71 61,51 75,45 75,71" fill={E} />
    </svg>
  );
}

const REDUCED = typeof window !== "undefined" && window.matchMedia
  && window.matchMedia("(prefers-reduced-motion: reduce)").matches;

function CountUp({ to, dur = 900, decimals = 0 }) {
  const [v, setV] = React.useState(REDUCED ? to : 0);
  React.useEffect(() => {
    if (REDUCED) { setV(to); return; }
    let raf, start;
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const step = (ts) => {
      if (!start) start = ts;
      const p = Math.min((ts - start) / dur, 1);
      setV(ease(p) * to);
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [to]);
  return <>{decimals ? v.toFixed(decimals) : Math.round(v)}</>;
}

function Ring({ pct, size = 88, stroke = 9, label, sub, tone = "emerald" }) {
  const r = (size - stroke) / 2;
  const circ = 2 * Math.PI * r;
  const [val, setVal] = React.useState(REDUCED ? pct : 0);
  React.useEffect(() => { const t = setTimeout(() => setVal(pct), 80); return () => clearTimeout(t); }, [pct]);
  const color = tone === "warn" ? "var(--st-warn-fg)" : tone === "err" ? "var(--st-err-fg)" : "var(--tge-emerald)";
  return (
    <div style={{ position: "relative", width: size, height: size, flex: "0 0 auto" }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--tge-slate-100)" strokeWidth={stroke} />
        <circle className="ring-arc" cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color}
                strokeWidth={stroke} strokeLinecap="round" strokeDasharray={circ}
                strokeDashoffset={circ * (1 - val / 100)} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 900, fontSize: size * 0.26, lineHeight: 1, letterSpacing: "-0.02em" }}>
            <CountUp to={pct} />%
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Icon, Badge, Conf, Logo, CountUp, Ring, fmtEUR, ROUTE_STATUS, DOC_STATUS });
