// Shared primitives for Meridian Sales CRM. Exposed on window for cross-file use.

/* ---------- ICONS (24px stroke) ---------- */
const Icon = ({ name, size = 18, stroke = "currentColor", strokeWidth = 1.6 }) => {
  const paths = {
    home: <><path d="M3 11l9-8 9 8" /><path d="M5 10v10h14V10" /></>,
    leads: <><circle cx="9" cy="8" r="3.5" /><path d="M3 20c0-3.3 2.7-6 6-6s6 2.7 6 6" /><circle cx="17" cy="9" r="2.5" /><path d="M15 20c0-2 1-3.5 2.5-4.3" /></>,
    pipeline: <><rect x="3" y="4" width="5" height="16" rx="1" /><rect x="10" y="4" width="5" height="11" rx="1" /><rect x="17" y="4" width="4" height="7" rx="1" /></>,
    tasks: <><path d="M9 11l3 3 8-8" /><path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" /></>,
    building: <><rect x="4" y="3" width="16" height="18" rx="1.5" /><path d="M9 7h2M13 7h2M9 11h2M13 11h2M9 15h2M13 15h2" /><path d="M10 21v-3h4v3" /></>,
    payments: <><rect x="2" y="6" width="20" height="13" rx="2" /><path d="M2 11h20" /><path d="M6 16h4" /></>,
    chart: <><path d="M3 3v18h18" /><path d="M7 14l4-4 3 3 5-6" /></>,
    team: <><circle cx="9" cy="8" r="3.5" /><path d="M3 20c0-3.3 2.7-6 6-6s6 2.7 6 6" /><circle cx="17" cy="9" r="2.5" /><path d="M15 20c0-2 1-3.5 2.5-4.3" /></>,
    settings: <><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.7 1.7 0 00.3 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.8.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.3-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.3H9a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.8-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.3 1.8V9a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z" /></>,
    search: <><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.3-4.3" /></>,
    plus: <><path d="M12 5v14M5 12h14" /></>,
    bell: <><path d="M6 8a6 6 0 1112 0c0 7 3 7 3 9H3c0-2 3-2 3-9z" /><path d="M10 21a2 2 0 004 0" /></>,
    chevronDown: <><path d="M6 9l6 6 6-6" /></>,
    chevronRight: <><path d="M9 6l6 6-6 6" /></>,
    chevronLeft: <><path d="M15 6l-6 6 6 6" /></>,
    sparkles: <><path d="M12 3l1.8 4.6L18 9.5l-4.2 1.9L12 16l-1.8-4.6L6 9.5l4.2-1.9z" /><path d="M19 14l.7 1.8 1.8.7-1.8.7-.7 1.8-.7-1.8-1.8-.7 1.8-.7z" /></>,
    check: <><path d="M5 12l5 5 9-11" /></>,
    x: <><path d="M6 6l12 12M6 18L18 6" /></>,
    phone: <><path d="M22 16.9v3a2 2 0 01-2.2 2 19.8 19.8 0 01-8.6-3.1 19.5 19.5 0 01-6-6 19.8 19.8 0 01-3.1-8.7A2 2 0 014.1 2h3a2 2 0 012 1.7c.1.9.3 1.8.6 2.7a2 2 0 01-.5 2.1L8 9.6a16 16 0 006 6l1.1-1.1a2 2 0 012.1-.5c.9.3 1.8.5 2.7.6a2 2 0 011.7 2z" /></>,
    mail: <><rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 6 9-6" /></>,
    note: <><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" /></>,
    upload: <><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" /><path d="M17 8l-5-5-5 5" /><path d="M12 3v12" /></>,
    download: <><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" /><path d="M7 10l5 5 5-5" /><path d="M12 15V3" /></>,
    calendar: <><rect x="3" y="4" width="18" height="17" rx="2" /><path d="M3 9h18M8 2v4M16 2v4" /></>,
    user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8" /></>,
    key: <><circle cx="8" cy="15" r="4" /><path d="M11 12l9-9M17 6l2 2M14 9l2 2" /></>,
    bed: <><path d="M3 18v-6a2 2 0 012-2h14a2 2 0 012 2v6" /><path d="M3 14h18M3 18v2M21 18v2" /><path d="M7 10V8a2 2 0 012-2h6a2 2 0 012 2v2" /></>,
    ruler: <><rect x="2" y="8" width="20" height="8" rx="1" transform="rotate(0 12 12)" /><path d="M6 8v3M10 8v4M14 8v3M18 8v4" /></>,
    eye: <><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z" /><circle cx="12" cy="12" r="3" /></>,
    send: <><path d="M22 2L11 13" /><path d="M22 2l-7 20-4-9-9-4z" /></>,
    moon: <><path d="M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z" /></>,
    sun: <><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M5 5l1.4 1.4M17.6 17.6L19 19M2 12h2M20 12h2M5 19l1.4-1.4M17.6 6.4L19 5" /></>,
    pin: <><path d="M12 21s7-6.2 7-11a7 7 0 10-14 0c0 4.8 7 11 7 11z" /><circle cx="12" cy="10" r="2.5" /></>,
    handshake: <><path d="M8 11l2-2 2 2 3-3 4 4-5 5-2-2" /><path d="M8 11l-3 3 2 2" /><path d="M3 8l4-4 4 2" /></>,
    doc: <><path d="M6 2h8l4 4v14a2 2 0 01-2 2H6a2 2 0 01-2-2V4a2 2 0 012-2z" /><path d="M14 2v4h4M8 13h8M8 17h6" /></>,
    grid: <><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /></>,
    list: <><path d="M3 6h18M3 12h18M3 18h18" /></>,
    filter: <><path d="M22 3H2l8 9.5V19l4 2v-8.5z" /></>,
    arrowRight: <><path d="M5 12h14M13 6l6 6-6 6" /></>,
    star: <><path d="M12 2l3 7 7 1-5 5 1 7-6-3-6 3 1-7-5-5 7-1z" /></>,
    clock: <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
    euro: <><path d="M18 7a6 6 0 100 10M4 10h8M4 14h7" /></>,
    device: <><rect x="6" y="2" width="12" height="20" rx="2.5" /><path d="M11 18.5h2" /></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" style={{ flexShrink: 0 }}>
      {paths[name] || null}
    </svg>
  );
};

/* ---------- STATUS PILL ---------- */
const PILL_TONES = {
  neutral: { bg: "var(--pill-neutral-bg)", fg: "var(--pill-neutral-fg)" },
  // lead pipeline
  New: { bg: "rgba(99,102,241,0.14)", fg: "#4f46e5" },
  Qualified: { bg: "rgba(14,165,233,0.15)", fg: "#0c81b8" },
  Viewing: { bg: "rgba(245,158,11,0.16)", fg: "#b46a08" },
  Offer: { bg: "rgba(139,92,246,0.16)", fg: "#7c3aed" },
  Reservation: { bg: "rgba(20,184,166,0.16)", fg: "#0d9488" },
  Closed: { bg: "rgba(34,160,94,0.16)", fg: "#1f8a52" },
  Lost: { bg: "rgba(120,113,108,0.16)", fg: "#78716c" },
  // unit
  Available: { bg: "rgba(34,160,94,0.15)", fg: "#1f8a52" },
  Reserved: { bg: "rgba(245,158,11,0.16)", fg: "#b46a08" },
  Sold: { bg: "rgba(120,113,108,0.16)", fg: "#6e6a62" },
  // payments
  Paid: { bg: "rgba(34,160,94,0.15)", fg: "#1f8a52" },
  Pending: { bg: "rgba(245,158,11,0.16)", fg: "#b46a08" },
  Overdue: { bg: "rgba(217,84,74,0.15)", fg: "#cf4436" },
  Refunded: { bg: "rgba(120,113,108,0.16)", fg: "#78716c" },
};
const Pill = ({ tone = "neutral", children, dot = false, size = "md" }) => {
  const t = PILL_TONES[tone] || PILL_TONES.neutral;
  const padding = size === "sm" ? "2px 9px" : "3px 11px";
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, padding, borderRadius: 999, background: t.bg, color: t.fg, fontSize: size === "sm" ? 11 : 12, fontWeight: 600, lineHeight: 1.25, whiteSpace: "nowrap" }}>
      {dot && <span style={{ width: 6, height: 6, borderRadius: 999, background: "currentColor" }} />}
      {children}
    </span>
  );
};
const STAGE_COLOR = { New: "#6366f1", Qualified: "#0ea5e9", Viewing: "#f59e0b", Offer: "#8b5cf6", Reservation: "#14b8a6", Closed: "#1f8a52", Lost: "#78716c" };

/* ---------- AVATAR ---------- */
const Avatar = ({ initials, size = 32, color = "var(--brand)", img }) => (
  <div style={{ width: size, height: size, borderRadius: 999, background: color, color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 650, fontSize: size * 0.4, flexShrink: 0, overflow: "hidden" }}>
    {initials}
  </div>
);

/* ---------- MONEY ---------- */
const CCY = { EUR: { sym: "€", code: "EUR" }, USD: { sym: "$", code: "USD" }, GBP: { sym: "£", code: "GBP" } };
let ACTIVE_CCY = "EUR";
const setCurrency = (c) => { ACTIVE_CCY = c; };
const money = (n, ccy) => {
  const c = CCY[ccy || ACTIVE_CCY] || CCY.EUR;
  return c.sym + Math.round(n).toLocaleString("en-US");
};
const moneyK = (n, ccy) => {
  const c = CCY[ccy || ACTIVE_CCY] || CCY.EUR;
  if (n >= 1000000) return c.sym + (n / 1000000).toFixed(2).replace(/\.00$/, "") + "M";
  if (n >= 1000) return c.sym + Math.round(n / 1000) + "k";
  return c.sym + n;
};

/* ---------- CHARTS ---------- */
const Sparkline = ({ data, w = 80, h = 24, color = "currentColor", fill = false }) => {
  const max = Math.max(...data), min = Math.min(...data), range = max - min || 1, step = w / (data.length - 1);
  const pts = data.map((v, i) => [i * step, h - ((v - min) / range) * (h - 4) - 2]);
  const d = pts.map((p, i) => (i === 0 ? `M ${p[0]} ${p[1]}` : `L ${p[0]} ${p[1]}`)).join(" ");
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: "block" }}>
      {fill && <path d={`${d} L ${w} ${h} L 0 ${h} Z`} fill={color} fillOpacity={0.12} />}
      <path d={d} fill="none" stroke={color} strokeWidth="1.7" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
};
const FunnelChart = ({ stages, color = "var(--brand)" }) => {
  const max = Math.max(...stages.map((s) => s.value));
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
      {stages.map((s, i) => {
        const pct = (s.value / max) * 100;
        return (
          <div key={s.label} style={{ display: "grid", gridTemplateColumns: "104px 1fr 40px", alignItems: "center", gap: 12, fontSize: 13 }}>
            <span style={{ color: "var(--text-muted)" }}>{s.label}</span>
            <div style={{ height: 24, background: "rgba(127,127,127,0.09)", borderRadius: 5, overflow: "hidden" }}>
              <div style={{ width: `${pct}%`, height: "100%", background: STAGE_COLOR[s.label] || color, opacity: 0.9, borderRadius: 5, transition: "width .5s ease" }} />
            </div>
            <span style={{ textAlign: "right", fontVariantNumeric: "tabular-nums", fontWeight: 600 }}>{s.value}</span>
          </div>
        );
      })}
    </div>
  );
};
const BarMini = ({ data, w = 120, h = 36, color = "var(--brand)", labels }) => {
  const max = Math.max(...data), bw = w / data.length - 4;
  return (
    <svg width="100%" height={h + (labels ? 14 : 0)} viewBox={`0 0 ${w} ${h + (labels ? 14 : 0)}`} preserveAspectRatio="none" style={{ display: "block" }}>
      {data.map((v, i) => {
        const bh = Math.max(2, (v / max) * (h - 4));
        return <rect key={i} x={i * (bw + 4) + 2} y={h - bh} width={bw} height={bh} fill={color} opacity={0.35 + (v / max) * 0.55} rx={2} />;
      })}
    </svg>
  );
};

/* ---------- DATA TABLE ---------- */
function RCDataTable({ data, columns, views = [], searchKeys = [], onRowClick, bulkActions = [], empty }) {
  const [view, setView] = React.useState(views[0]?.id || null);
  const [q, setQ] = React.useState("");
  const [sort, setSort] = React.useState(null);
  const [sel, setSel] = React.useState(new Set());

  const activeView = views.find((v) => v.id === view);
  let rows = data.filter((r) => activeView?.predicate ? activeView.predicate(r) : true);
  if (q.trim()) {
    const t = q.toLowerCase();
    rows = rows.filter((r) => searchKeys.some((k) => String(r[k] || "").toLowerCase().includes(t)));
  }
  if (sort) {
    rows = [...rows].sort((a, b) => {
      const av = a[sort.key], bv = b[sort.key];
      const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av).localeCompare(String(bv));
      return sort.dir === "asc" ? cmp : -cmp;
    });
  }
  const toggleSort = (key) => setSort((s) => s && s.key === key ? (s.dir === "asc" ? { key, dir: "desc" } : null) : { key, dir: "asc" });
  const allSel = rows.length > 0 && rows.every((r) => sel.has(r.id));
  const toggleAll = () => setSel(allSel ? new Set() : new Set(rows.map((r) => r.id)));
  const toggleOne = (id) => setSel((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });

  return (
    <div className="rc-card rc-table-card">
      <div className="rc-table-toolbar">
        {views.length > 0 && (
          <div className="rc-views">
            {views.map((v) => (
              <button key={v.id} className={`rc-view ${view === v.id ? "is-active" : ""}`} onClick={() => setView(v.id)}>
                {v.label}{v.count != null && <span className="rc-view-count">{v.count}</span>}
              </button>
            ))}
          </div>
        )}
        {searchKeys.length > 0 && (
          <div className="rc-table-search">
            <Icon name="search" size={14} />
            <input placeholder="Search…" value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
        )}
      </div>

      {sel.size > 0 && bulkActions.length > 0 && (
        <div className="rc-bulkbar">
          <strong>{sel.size} selected</strong>
          <div style={{ display: "flex", gap: 6, marginLeft: "auto" }}>
            {bulkActions.map((a) => (
              <button key={a.label} className="rc-btn rc-btn-sm" onClick={() => { a.onClick([...sel]); setSel(new Set()); }}>
                {a.icon && <Icon name={a.icon} size={13} />}{a.label}
              </button>
            ))}
            <button className="rc-btn-ghost rc-btn-sm" onClick={() => setSel(new Set())}>Clear</button>
          </div>
        </div>
      )}

      {rows.length === 0 ? (
        <div className="rc-empty">
          <div className="rc-empty-title">{empty?.title || "Nothing here yet"}</div>
          <div className="rc-empty-body">{empty?.body}</div>
          {empty?.cta}
        </div>
      ) : (
        <div style={{ overflowX: "auto" }}>
          <table className="rc-table">
            <thead>
              <tr>
                {bulkActions.length > 0 && (
                  <th className="rc-checkcol"><span className={`rc-cb ${allSel ? "is-on" : ""}`} onClick={toggleAll}>{allSel && <Icon name="check" size={11} />}</span></th>
                )}
                {columns.map((c) => (
                  <th key={c.key} className={`${c.align === "right" ? "rc-num" : ""} ${c.sortable ? "is-sortable" : ""}`} onClick={() => c.sortable && toggleSort(c.key)}>
                    {c.label}
                    {sort?.key === c.key && <span className="rc-th-arrow">{sort.dir === "asc" ? "▲" : "▼"}</span>}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {rows.map((r) => (
                <tr key={r.id} onClick={() => onRowClick && onRowClick(r)}>
                  {bulkActions.length > 0 && (
                    <td className="rc-checkcol" onClick={(e) => { e.stopPropagation(); toggleOne(r.id); }}>
                      <span className={`rc-cb ${sel.has(r.id) ? "is-on" : ""}`}>{sel.has(r.id) && <Icon name="check" size={11} />}</span>
                    </td>
                  )}
                  {columns.map((c) => (
                    <td key={c.key} className={c.align === "right" ? "rc-num" : ""}>{c.render ? c.render(r) : r[c.key]}</td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

/* ---------- TOASTS ---------- */
const ToastCtx = React.createContext(() => {});
const useToast = () => React.useContext(ToastCtx);
function ToastProvider({ children }) {
  const [toasts, setToasts] = React.useState([]);
  const push = React.useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((s) => [...s, { ...t, id }]);
    setTimeout(() => setToasts((s) => s.filter((x) => x.id !== id)), 2800);
  }, []);
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="rc-toasts">
        {toasts.map((t) => (
          <div key={t.id} className={`rc-toast ${t.tone === "ok" ? "rc-toast-ok" : ""}`}>
            <Icon name={t.tone === "ok" ? "check" : "sparkles"} size={15} />
            <div><strong>{t.title}</strong>{t.body && <span style={{ opacity: 0.85 }}> · {t.body}</span>}</div>
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}

/* ---------- MODAL ---------- */
function Modal({ open, onClose, title, children, foot }) {
  if (!open) return null;
  return (
    <div className="rc-modal-scrim" onClick={onClose}>
      <div className="rc-modal" onClick={(e) => e.stopPropagation()}>
        <div className="rc-modal-head">
          <div className="rc-modal-title">{title}</div>
          <button className="rc-iconbtn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        <div className="rc-modal-body">{children}</div>
        {foot && <div className="rc-modal-foot">{foot}</div>}
      </div>
    </div>
  );
}

Object.assign(window, { Icon, Pill, STAGE_COLOR, Avatar, money, moneyK, setCurrency, Sparkline, FunnelChart, BarMini, RCDataTable, ToastProvider, useToast, Modal });
