// Shared UI primitives + icons. Keep it lean — no styles object collisions.

// ---- Icons (lucide-style, 1.75 stroke) ----
const Ico = (props) => {
  const d = props.d;
  const size = props.size || 16;
  const fill = props.fill || 'none';
  const sw = props.sw === undefined ? 1.75 : props.sw;
  return (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
    {typeof d === 'string' ? <path d={d} /> : d}
  </svg>
);};

const _ie = React.createElement;
const _Ico = Ico;
const _path = (d) => _ie('path', { d });
const _rect = (props) => _ie('rect', props);
const _circle = (props) => _ie('circle', props);

const Icon = {
  Home:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M3 11l9-8 9 8M5 10v10h14V10" })),
  Grid:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 3, y: 3, width: 7, height: 7, rx: 1 }),
    _ie('rect', { key: 2, x: 14, y: 3, width: 7, height: 7, rx: 1 }),
    _ie('rect', { key: 3, x: 3, y: 14, width: 7, height: 7, rx: 1 }),
    _ie('rect', { key: 4, x: 14, y: 14, width: 7, height: 7, rx: 1 }),
  ] })),
  Pipeline:(p) => _ie(_Ico, Object.assign({}, p, { d: _path("M3 6h18M3 12h12M3 18h6") })),
  Cash:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 2, y: 6, width: 20, height: 12, rx: 2 }),
    _ie('circle', { key: 2, cx: 12, cy: 12, r: 3 }),
  ] })),
  Trophy:  (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('path', { key: 1, d: "M8 4h8v6a4 4 0 01-8 0V4z" }),
    _ie('path', { key: 2, d: "M5 6H3v2a3 3 0 003 3" }),
    _ie('path', { key: 3, d: "M19 6h2v2a3 3 0 01-3 3" }),
    _ie('path', { key: 4, d: "M9 14h6v2H9zM8 20h8" }),
  ] })),
  Folder:  (p) => _ie(_Ico, Object.assign({}, p, { d: "M3 6a2 2 0 012-2h4l2 2h8a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V6z" })),
  Megaphone:(p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('path', { key: 1, d: "M3 11v3a1 1 0 001 1h3l4 4V6L7 10H4a1 1 0 00-1 1z" }),
    _ie('path', { key: 2, d: "M16 8a4 4 0 010 8" }),
  ] })),
  Link:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('path', { key: 1, d: "M10 14a4 4 0 005.66 0l3-3a4 4 0 10-5.66-5.66l-1 1" }),
    _ie('path', { key: 2, d: "M14 10a4 4 0 00-5.66 0l-3 3a4 4 0 105.66 5.66l1-1" }),
  ] })),
  Book:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M4 4h12a3 3 0 013 3v13H7a3 3 0 01-3-3V4z" })),
  Check:   (p) => _ie(_Ico, Object.assign({}, p, { d: "M5 12l4 4 10-10" })),
  Chevron: (p) => _ie(_Ico, Object.assign({}, p, { d: "M9 6l6 6-6 6" })),
  ChevronD:(p) => _ie(_Ico, Object.assign({}, p, { d: "M6 9l6 6 6-6" })),
  Search:  (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('circle', { key: 1, cx: 11, cy: 11, r: 7 }),
    _ie('path', { key: 2, d: "M21 21l-4.35-4.35" }),
  ] })),
  Bell:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M6 8a6 6 0 1112 0c0 7 3 8 3 8H3s3-1 3-8zM10 21a2 2 0 004 0" })),
  Bolt:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M13 2L4 14h7l-1 8 9-12h-7l1-8z" })),
  Sun:     (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('circle', { key: 1, cx: 12, cy: 12, r: 4 }),
    _ie('path', { key: 2, d: "M12 2v2M12 20v2M4 12H2M22 12h-2M5 5l1.5 1.5M17.5 17.5L19 19M5 19l1.5-1.5M17.5 6.5L19 5" }),
  ] })),
  Moon:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M21 13A9 9 0 1111 3a7 7 0 0010 10z", fill: "currentColor" })),
  Layout:  (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 3, y: 3, width: 18, height: 18, rx: 2 }),
    _ie('path', { key: 2, d: "M3 9h18M9 21V9" }),
  ] })),
  Table:   (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 3, y: 3, width: 18, height: 18, rx: 2 }),
    _ie('path', { key: 2, d: "M3 9h18M3 15h18M9 3v18M15 3v18" }),
  ] })),
  Card:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 3, y: 4, width: 8, height: 16, rx: 1 }),
    _ie('rect', { key: 2, x: 13, y: 4, width: 8, height: 7, rx: 1 }),
    _ie('rect', { key: 3, x: 13, y: 13, width: 8, height: 7, rx: 1 }),
  ] })),
  Plus:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M12 5v14M5 12h14" })),
  Filter:  (p) => _ie(_Ico, Object.assign({}, p, { d: "M3 5h18l-7 9v6l-4-2v-4z" })),
  Copy:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 8, y: 8, width: 13, height: 13, rx: 2 }),
    _ie('path', { key: 2, d: "M16 8V5a2 2 0 00-2-2H5a2 2 0 00-2 2v9a2 2 0 002 2h3" }),
  ] })),
  Send:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M3 12L21 3l-9 18-2-7-7-2z" })),
  Play:    (p) => _ie(_Ico, Object.assign({}, p, { d: "M6 4l14 8-14 8V4z", fill: "currentColor", sw: 0 })),
  Lock:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 4, y: 11, width: 16, height: 10, rx: 2 }),
    _ie('path', { key: 2, d: "M8 11V7a4 4 0 018 0v4" }),
  ] })),
  Flame:   (p) => _ie(_Ico, Object.assign({}, p, { d: "M12 3s4 4 4 8a4 4 0 11-8 0c0-1 1-2 1-2s-3-1-3-4c0 0 3 0 6 5z" })),
  Mail:    (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('rect', { key: 1, x: 3, y: 5, width: 18, height: 14, rx: 2 }),
    _ie('path', { key: 2, d: "M3 7l9 6 9-6" }),
  ] })),
  Phone:   (p) => _ie(_Ico, Object.assign({}, p, { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6A19.79 19.79 0 012.12 4.18 2 2 0 014.11 2h3a2 2 0 012 1.72c.13.96.36 1.9.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0122 16.92z" })),
  Clock:   (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('circle', { key: 1, cx: 12, cy: 12, r: 9 }),
    _ie('path', { key: 2, d: "M12 7v5l3 2" }),
  ] })),
  Alert:   (p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('path', { key: 1, d: "M12 3l10 17H2L12 3z" }),
    _ie('path', { key: 2, d: "M12 10v4M12 17.5v.5" }),
  ] })),
  ArrowUp: (p) => _ie(_Ico, Object.assign({}, p, { d: "M12 19V5M5 12l7-7 7 7" })),
  ArrowDn: (p) => _ie(_Ico, Object.assign({}, p, { d: "M12 5v14M19 12l-7 7-7-7" })),
  Settings:(p) => _ie(_Ico, Object.assign({}, p, { d: [
    _ie('circle', { key: 1, cx: 12, cy: 12, r: 3 }),
    _ie('path', { key: 2, d: "M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09A1.65 1.65 0 008 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H2a2 2 0 110-4h.09A1.65 1.65 0 004.6 8a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V2a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H22a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z" }),
  ] })),
  Logo:    (p) => {
    const sz = (p && p.size) || 22;
    return _ie('svg', { width: sz, height: sz, viewBox: "0 0 24 24", fill: "none" },
      _ie('rect', { key: 1, x: 2, y: 2, width: 20, height: 20, rx: 5, fill: "var(--accent)" }),
      _ie('path', { key: 2, d: "M9 6h7v8.5a3.5 3.5 0 11-7 0V12", stroke: "var(--ink-on-accent)", strokeWidth: 2.4, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })
    );
  },
};

// ---- Format helpers ----
const fmtMoney = (n, opts) => {
  const o = opts || {};
  const cents = o.cents === true;
  const sign = o.sign === true;
  const s = '$' + Math.abs(n).toLocaleString('en-US', { minimumFractionDigits: cents ? 2 : 0, maximumFractionDigits: cents ? 2 : 0 });
  if (sign && n > 0) return '+' + s;
  if (n < 0) return '−' + s;
  return s;
};
const fmtPct = (n, digits) => (n * 100).toFixed(digits === undefined ? 1 : digits) + '%';
const fmtPctRaw = (n, digits) => (n).toFixed(digits === undefined ? 1 : digits) + '%';

// ---- Pills, chips, badges ----
const Pill = ({ tone, children, soft }) => {
  const tones = {
    accent:  { bg: 'color-mix(in oklab, var(--accent) 14%, transparent)', fg: 'var(--accent-ink)', bd: 'color-mix(in oklab, var(--accent) 28%, transparent)' },
    success: { bg: 'color-mix(in oklab, var(--ok) 14%, transparent)',     fg: 'var(--ok-ink)',     bd: 'color-mix(in oklab, var(--ok) 28%, transparent)' },
    warn:    { bg: 'color-mix(in oklab, var(--warn) 16%, transparent)',   fg: 'var(--warn-ink)',   bd: 'color-mix(in oklab, var(--warn) 32%, transparent)' },
    danger:  { bg: 'color-mix(in oklab, var(--danger) 14%, transparent)', fg: 'var(--danger-ink)', bd: 'color-mix(in oklab, var(--danger) 28%, transparent)' },
    neutral: { bg: 'var(--surface-2)', fg: 'var(--ink-2)', bd: 'var(--line)' },
  };
  const t = tones[tone || 'neutral'];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '2px 8px', borderRadius: 999, fontSize: 11.5, fontWeight: 600,
      letterSpacing: 0.1, background: soft ? 'transparent' : t.bg, color: t.fg,
      border: '1px solid ' + t.bd, lineHeight: 1.5, whiteSpace: 'nowrap'
    }}>{children}</span>
  );
};

const EntityChip = ({ entity, code, name, mono, size }) => {
  const c = (entity && entity.code) || code || '';
  const n = (entity && (entity.short || entity.name)) || name || '';
  const tint = (entity && entity.color) || 'var(--ink-1)';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '3px 8px 3px 4px', borderRadius: 6,
      background: 'var(--surface-2)', border: '1px solid var(--line)',
      fontSize: size === 'md' ? 13 : 12, fontWeight: 600, color: 'var(--ink-1)', whiteSpace: 'nowrap'
    }}>
      <span style={{
        width: size === 'md' ? 22 : 18, height: size === 'md' ? 22 : 18,
        borderRadius: 4, display: 'grid', placeItems: 'center',
        background: tint, color: '#fff',
        fontSize: 10, fontWeight: 800, fontFamily: 'var(--mono)'
      }}>{c}</span>
      {!mono && <span>{n}</span>}
    </span>
  );
};

const StagePill = ({ stage, won }) => {
  const label = won ? 'Funded' : (stage && (stage.label || stage.short)) || 'Lead';
  const id = stage && stage.id;
  const dot = won ? 'var(--ok)'
    : id === 'declined' ? 'var(--danger)'
    : id === 'lead' ? 'var(--ink-3)'
    : id === 'apptset' || id === 'submitted' ? 'var(--accent)'
    : id === 'underwriting' || id === 'approved' ? 'var(--accent)'
    : 'var(--ink-3)';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '2px 8px 2px 6px', borderRadius: 999, fontSize: 11.5, fontWeight: 600,
      background: 'var(--surface-2)', color: 'var(--ink-1)', border: '1px solid var(--line)'
    }}>
      <span style={{ width: 6, height: 6, borderRadius: 999, background: dot }} />
      {label}
    </span>
  );
};

// ---- KPI ----
const KPI = ({ label, value, delta, deltaTone, sub, accent }) => (
  <div style={{
    background: 'var(--surface-1)', border: '1px solid var(--line)', borderRadius: 10,
    padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 6,
    minWidth: 0, position: 'relative', overflow: 'hidden'
  }}>
    {accent && <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 3, background: 'var(--accent)' }} />}
    <div style={{ fontSize: 11.5, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.4, fontWeight: 600 }}>{label}</div>
    <div style={{ fontSize: 24, fontWeight: 700, fontFamily: 'var(--display)', color: 'var(--ink-1)', letterSpacing: -0.3, lineHeight: 1.1 }}>{value}</div>
    {(delta || sub) && (
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--ink-2)' }}>
        {delta && <span style={{
          color: deltaTone === 'down' ? 'var(--danger-ink)' : 'var(--ok-ink)',
          fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 3
        }}>
          {deltaTone === 'down' ? <Icon.ArrowDn size={12} /> : <Icon.ArrowUp size={12} />}
          {delta}
        </span>}
        {sub && <span>{sub}</span>}
      </div>
    )}
  </div>
);

// ---- Card ----
const Card = ({ title, subtitle, right, children, pad, flush }) => (
  <section style={{
    background: 'var(--surface-1)', border: '1px solid var(--line)', borderRadius: 10,
    overflow: 'hidden', display: 'flex', flexDirection: 'column', minHeight: 0
  }}>
    {(title || right) && (
      <header style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
        padding: '12px 16px', borderBottom: '1px solid var(--line)'
      }}>
        <div style={{ minWidth: 0 }}>
          {title && <div style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--ink-1)' }}>{title}</div>}
          {subtitle && <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{subtitle}</div>}
        </div>
        {right && <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>{right}</div>}
      </header>
    )}
    <div style={{ padding: flush ? 0 : (pad === undefined ? 16 : pad), minHeight: 0 }}>{children}</div>
  </section>
);

// ---- Button ----
const Button = ({ kind, size, onClick, children, icon, disabled, full, type }) => {
  const k = kind || 'ghost';
  const sz = size || 'md';
  const styles = {
    primary: { bg: 'var(--accent)', fg: 'var(--ink-on-accent)', bd: 'var(--accent)' },
    ghost:   { bg: 'var(--surface-1)', fg: 'var(--ink-1)', bd: 'var(--line)' },
    soft:    { bg: 'var(--surface-2)', fg: 'var(--ink-1)', bd: 'transparent' },
    danger:  { bg: 'var(--danger)', fg: '#fff', bd: 'var(--danger)' },
    link:    { bg: 'transparent', fg: 'var(--accent-ink)', bd: 'transparent' },
  }[k];
  const sizes = { sm: { p: '4px 10px', fs: 12, h: 26 }, md: { p: '6px 12px', fs: 12.5, h: 32 }, lg: { p: '10px 16px', fs: 14, h: 40 } }[sz];
  return (
    <button type={type || 'button'} onClick={onClick} disabled={disabled} style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
      padding: sizes.p, height: sizes.h, fontSize: sizes.fs, fontWeight: 600,
      background: styles.bg, color: styles.fg, border: '1px solid ' + styles.bd,
      borderRadius: 6, cursor: disabled ? 'not-allowed' : 'pointer',
      opacity: disabled ? 0.5 : 1, width: full ? '100%' : 'auto', whiteSpace: 'nowrap',
      transition: 'background 0.15s, border-color 0.15s, transform 0.05s',
      fontFamily: 'inherit'
    }}>
      {icon}{children}
    </button>
  );
};

// ---- Sparkline ----
const Sparkline = ({ data, w, h, color, fill }) => {
  const W = w || 120, H = h || 32;
  const min = Math.min(...data), max = Math.max(...data);
  const span = (max - min) || 1;
  const pts = data.map((v, i) => [(i / (data.length - 1)) * W, H - 2 - ((v - min) / span) * (H - 4)]);
  const d = pts.map((p, i) => (i === 0 ? 'M' : 'L') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  const area = d + ' L ' + W + ' ' + H + ' L 0 ' + H + ' Z';
  const c = color || 'var(--accent)';
  return (
    <svg width={W} height={H} style={{ display: 'block' }}>
      {fill && <path d={area} fill={c} opacity={0.12} />}
      <path d={d} fill="none" stroke={c} strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
};

// ---- Stage funnel bar (per-row pipeline progress) ----
const StageBar = ({ stages, currentStageId, won, stalled }) => {
  // Funnel mode: an array of { label, count, color }
  if (Array.isArray(stages)) {
    const total = stages.reduce((a, s) => a + (s.count || 0), 0) || 1;
    return (
      <div style={{ display: 'flex', gap: 2, height: 8, borderRadius: 4, overflow: 'hidden', background: 'var(--surface-2)' }}>
        {stages.map((s, i) => (
          <div key={i} title={s.label + ': ' + s.count} style={{
            width: (((s.count || 0) / total) * 100) + '%',
            background: s.color || 'var(--accent)',
            minWidth: s.count > 0 ? 4 : 0
          }} />
        ))}
      </div>
    );
  }
  // Per-row mode: progress along the deal stages
  const all = (window.JFJ && window.JFJ.PIPELINE_STAGES) || [];
  const filtered = all.filter(s => s.id !== 'declined');
  const idx = won ? filtered.length - 1 : Math.max(0, filtered.findIndex(s => s.id === currentStageId));
  return (
    <div style={{ display: 'flex', gap: 3, alignItems: 'center' }}>
      {filtered.map((s, i) => {
        const active = i <= idx;
        const isCurrent = i === idx;
        const color = won ? 'var(--ok)' : stalled && isCurrent ? 'var(--warn)' : active ? 'var(--accent)' : 'var(--line)';
        return (
          <div key={s.id} title={s.label} style={{
            flex: 1, height: 6, borderRadius: 3, background: color,
            opacity: active ? 1 : 0.6
          }} />
        );
      })}
    </div>
  );
};

Object.assign(window, {
  Ico, Icon, fmtMoney, fmtPct, fmtPctRaw,
  Pill, EntityChip, StagePill, KPI, Card, Button, Sparkline, StageBar,
});
