/* ============================================================
   WCW Product Hub — Shared UI components & icons
   ============================================================ */
const { useState, useRef, useEffect, useLayoutEffect } = React;

/* ---------- Icon set (simple line icons) ---------- */
const ICON_PATHS = {
  home: "M3 10.5 12 3l9 7.5M5 9.5V20h5v-6h4v6h5V9.5",
  board: "M4 4h6v16H4zM14 4h6v9h-6z",
  list: "M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01",
  plus: "M12 5v14M5 12h14",
  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",
  chevDown: "M6 9l6 6 6-6",
  chevRight: "M9 6l6 6-6 6",
  arrowRight: "M5 12h14M13 6l6 6-6 6",
  check: "M20 6 9 17l-5-5",
  clock: "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 6v6l4 2",
  alert: "M12 9v4M12 17h.01M10.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 0z",
  chat: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",
  activity: "M22 12h-4l-3 9L9 3l-3 9H2",
  user: "M20 21a8 8 0 1 0-16 0M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",
  users: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM23 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8",
  doc: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6",
  upload: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12",
  box: "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",
  tag: "M20.6 13.4 13.4 20.6a2 2 0 0 1-2.8 0l-7.2-7.2A2 2 0 0 1 2.8 12V4.8a2 2 0 0 1 2-2H12a2 2 0 0 1 1.4.6l7.2 7.2a2 2 0 0 1 0 2.8zM7.5 7.5h.01",
  truck: "M1 3h15v13H1zM16 8h4l3 3v5h-7M5.5 18.5a2 2 0 1 0 0 .01M18.5 18.5a2 2 0 1 0 0 .01",
  chart: "M3 3v18h18M7 16l4-5 3 3 5-7",
  store: "M3 9 4.5 4h15L21 9M4 9v11h16V9M4 9h16M9 20v-6h6v6",
  send: "M22 2 11 13M22 2l-7 20-4-9-9-4z",
  ring: "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20z",
  pin: "M12 21s-7-6.3-7-11a7 7 0 0 1 14 0c0 4.7-7 11-7 11zM12 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z",
  book: "M4 19.5A2.5 2.5 0 0 1 6.5 17H20M4 19.5A2.5 2.5 0 0 0 6.5 22H20V2H6.5A2.5 2.5 0 0 0 4 4.5z",
  sparkle: "M12 3l1.9 5.6L19.5 10l-5.6 1.9L12 17.5l-1.9-5.6L4.5 10l5.6-1.9z",
  filter: "M22 3H2l8 9.5V19l4 2v-8.5z",
  settings: "M12 15a3 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 1 1-4 0v-.1A1.6 1.6 0 0 0 7 19.4a1.6 1.6 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.6 1.6 0 0 0-1.1-2.7H1a2 2 0 1 1 0-4h.1A1.6 1.6 0 0 0 2.6 7a1.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 1.8.3H7a1.6 1.6 0 0 0 1-1.5V1a2 2 0 1 1 4 0v.1a1.6 1.6 0 0 0 2.7 1.1 1.6 1.6 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0-.3 1.8V7a1.6 1.6 0 0 0 1.5 1H23a2 2 0 1 1 0 4h-.1a1.6 1.6 0 0 0-1.5 1z",
  inbox: "M22 12h-6l-2 3h-4l-2-3H2M5.5 5h13l3.5 7v6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-6z",
  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",
  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",
  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",
  dollar: "M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6",
};

function Icon({ name, size = 18, stroke = 2, fill = "none", style }) {
  const d = ICON_PATHS[name];
  if (!d) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill}
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      style={{ flexShrink: 0, display: "block", ...style }}>
      {d.split("M").filter(Boolean).map((seg, i) => <path key={i} d={"M" + seg} />)}
    </svg>
  );
}

/* ---------- Avatar ---------- */
function Avatar({ name, init, color, size }) {
  const P = window.HUB_DATA.PEOPLE;
  const meta = name && P[name] ? P[name] : null;
  const i = init || (meta ? meta.init : (name ? name.split(" ").map(w => w[0]).slice(0, 2).join("") : "?"));
  const c = color || (meta ? meta.color : "var(--ink-3)");
  const cls = size ? `avatar ${size}` : "avatar";
  return <div className={cls} style={{ background: c }}>{i}</div>;
}

/* ---------- Stage pill ---------- */
function StagePill({ stage }) {
  const S = window.HUB_DATA.STAGES.find(s => s.id === stage);
  if (!S) return null;
  return <span className={`pill ${S.cls}`}><span className="pdot"></span>{S.name}</span>;
}

/* ---------- Aging ---------- */
function Aging({ days }) {
  const cls = days >= 7 ? "red" : days >= 4 ? "yellow" : "green";
  return <span className={`aging ${cls}`}>{days}d</span>;
}

/* ---------- Steps progress ---------- */
function Steps({ pct }) {
  const filled = Math.round((pct / 100) * 4);
  return (
    <span className="steps">
      {[0, 1, 2, 3].map(i => (
        <span key={i} className={`seg-bar ${i < filled ? "done" : i === filled ? "active" : ""}`}></span>
      ))}
      <span className="pct">{pct}%</span>
    </span>
  );
}

/* ---------- Progress ring (SVG) ---------- */
function Ring({ pct, size = 52 }) {
  const r = (size - 8) / 2, c = 2 * Math.PI * r;
  const off = c - (pct / 100) * c;
  return (
    <svg className="ring" width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--line-2)" strokeWidth="5" />
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--red)" strokeWidth="5"
        strokeLinecap="round" strokeDasharray={c} strokeDashoffset={off}
        transform={`rotate(-90 ${size / 2} ${size / 2})`} style={{ transition: "stroke-dashoffset .5s ease" }} />
      <text x="50%" y="52%" textAnchor="middle" dominantBaseline="middle"
        style={{ font: "800 14px var(--display)", fill: "var(--ink)" }}>{pct}%</text>
    </svg>
  );
}

/* ---------- Dismissible popover (click-outside) ---------- */
function useClickOutside(onClose) {
  const ref = useRef(null);
  useEffect(() => {
    function handle(e) { if (ref.current && !ref.current.contains(e.target)) onClose(); }
    document.addEventListener("mousedown", handle);
    return () => document.removeEventListener("mousedown", handle);
  }, [onClose]);
  return ref;
}

/* ---------- Rich select (code + description) ---------- */
function RichSelect({ value, onChange, source, placeholder }) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const opts = window.HUB_DATA.SOURCES[source] || [];
  const ref = useClickOutside(() => setOpen(false));
  const sel = opts.find(o => o.code === value);
  const filtered = opts.filter(o =>
    !q || o.name.toLowerCase().includes(q.toLowerCase()) || o.code.toLowerCase().includes(q.toLowerCase()));
  return (
    <div className="rselect" ref={ref}>
      <button type="button" className={`rselect-trigger ${open ? "open" : ""}`} onClick={() => setOpen(o => !o)}>
        {sel ? (
          <span className="rs-sel"><span className="tag code">{sel.code}</span><span style={{ fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{sel.name}</span></span>
        ) : <span className="rs-placeholder">{placeholder || "Select…"}</span>}
        <Icon name="chevDown" size={15} className="chev" />
      </button>
      {open && (
        <div className="rselect-menu">
          <div style={{ position: "sticky", top: 0, background: "var(--surface)", paddingBottom: 5 }}>
            <input className="inp" autoFocus placeholder="Search…" value={q} onChange={e => setQ(e.target.value)} style={{ fontSize: 12.5 }} />
          </div>
          {filtered.map(o => (
            <div key={o.code} className={`rselect-opt ${o.code === value ? "sel" : ""}`}
              onClick={() => { onChange(o.code); setOpen(false); setQ(""); }}>
              <span className="ro-code">{o.code}</span>
              <div><div className="ro-name">{o.name}</div><div className="ro-desc">{o.desc}</div></div>
            </div>
          ))}
          {filtered.length === 0 && <div style={{ padding: 14, fontSize: 12, color: "var(--ink-3)", textAlign: "center" }}>No matches</div>}
        </div>
      )}
    </div>
  );
}

/* ---------- Comment text with @mention highlighting ---------- */
function CommentText({ text }) {
  const names = Object.keys(window.HUB_DATA.PEOPLE);
  const parts = [];
  let rest = text, key = 0;
  while (rest.length) {
    let hit = null, idx = -1;
    for (const n of names) {
      const at = "@" + n;
      const p = rest.indexOf(at);
      if (p !== -1 && (idx === -1 || p < idx)) { idx = p; hit = at; }
    }
    if (idx === -1) { parts.push(rest); break; }
    if (idx > 0) parts.push(rest.slice(0, idx));
    parts.push(<span className="mention" key={key++}>{hit}</span>);
    rest = rest.slice(idx + hit.length);
  }
  return <span>{parts}</span>;
}

/* ---------- Toast ---------- */
function Toasts({ toasts }) {
  return (
    <div className="toast-wrap">
      {toasts.map(t => (
        <div className="toast" key={t.id}>
          <Icon name={t.icon || "check"} size={16} className="t-ico" style={{ color: "var(--live-soft)" }} />
          {t.msg}
        </div>
      ))}
    </div>
  );
}

Object.assign(window, {
  Icon, Avatar, StagePill, Aging, Steps, Ring,
  RichSelect, CommentText, Toasts, useClickOutside,
});
