// Shared primitives used across the dashboard.
// Lucide icons attached as window.Lucide via UMD CDN.

const { useState, useEffect, useRef } = React;

function Icon({ name, size = 16, color, strokeWidth = 1.5, style }) {
  const lib = window.lucide;
  if (!lib) return null;
  // Lucide UMD 0.378 exposes icons as PascalCase keys (e.g. lucide.LayoutDashboard).
  // Format: [tagName, attrs, [[childTag, childAttrs], ...]]
  const icon = lib[name];
  if (!icon || !Array.isArray(icon)) return null;
  const children = Array.isArray(icon[2]) ? icon[2] : [];
  function renderNode(node, key) {
    if (!Array.isArray(node)) return null;
    const [tag, attrs, kids] = node;
    const kidEls = Array.isArray(kids) ? kids.map((c, i) => renderNode(c, i)) : null;
    return React.createElement(tag, { key, ...attrs }, kidEls);
  }
  return (
    <svg
      width={size} height={size} viewBox="0 0 24 24"
      fill="none" stroke={color || 'currentColor'}
      strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
      style={style}
    >
      {children.map((c, i) => renderNode(c, i))}
    </svg>
  );
}
window.Icon = Icon;

function Pill({ variant = 'outline', size, onClick, children, type, disabled, style, className = '' }) {
  return (
    <button
      type={type || 'button'}
      onClick={onClick}
      disabled={disabled}
      style={style}
      className={`pill ${variant} ${size === 'sm' ? 'sm' : ''} ${className}`}
    >
      <span className="lbl">{children}</span>
    </button>
  );
}
window.Pill = Pill;

function Card({ title, sub, eyebrow, actions, children, pad, lift, style, className = '', onClick }) {
  return (
    <div
      className={`card ${pad === 'lg' ? 'card-pad-lg' : ''} ${pad === 'tight' ? 'card-tight' : ''} ${lift ? 'lift' : ''} ${className}`}
      style={style}
      onClick={onClick}
    >
      {(title || actions || eyebrow) && (
        <div className="card-head">
          <div>
            {eyebrow && <div className="card-eyebrow">{eyebrow}</div>}
            {title && <h3 className="card-title">{title}</h3>}
            {sub && <div className="card-sub">{sub}</div>}
          </div>
          {actions && <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>{actions}</div>}
        </div>
      )}
      {children}
    </div>
  );
}
window.Card = Card;

function StatusChip({ status }) {
  const map = {
    healthy: { cls: 'healthy', label: 'Healthy' },
    risk: { cls: 'risk', label: 'At risk' },
    churn: { cls: 'churn', label: 'Churn risk' },
    active: { cls: 'healthy', label: 'Active' },
    paused: { cls: 'risk', label: 'Paused' },
    review: { cls: 'risk', label: 'Needs review' },
    connected: { cls: 'connected', label: 'Connected' },
    disconnected: { cls: 'disconnected', label: 'Not connected' },
    new: { cls: '', label: 'New' },
    researching: { cls: 'risk', label: 'Researching' },
    pursuing: { cls: 'healthy', label: 'Pursuing' },
    passed: { cls: 'disconnected', label: 'Passed' },
  };
  const v = map[String(status).toLowerCase()] || { cls: '', label: status };
  return (
    <span className={`chip ${v.cls}`}>
      {v.cls && <span className="chip-dot" />}
      {v.label}
    </span>
  );
}
window.StatusChip = StatusChip;

function ScorePill({ score }) {
  let cls = 'lo';
  if (score >= 70) cls = 'hi';
  else if (score >= 40) cls = 'mid';
  return <span className={`score-pill ${cls}`}>{score}</span>;
}
window.ScorePill = ScorePill;

function Delta({ value }) {
  if (value == null || isNaN(value)) return null;
  const pos = value >= 0;
  return (
    <span className={`kpi-delta ${pos ? 'pos' : 'neg'}`}>
      <Icon name={pos ? 'ArrowUpRight' : 'ArrowDownRight'} size={12} />
      <span>{window.fmtDelta(value)}</span>
    </span>
  );
}
window.Delta = Delta;

function Sparkline({ data, color = 'var(--brand-red)', width = 72, height = 28 }) {
  if (!data || !data.length) return null;
  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1;
  const stepX = width / (data.length - 1);
  const pts = data.map((v, i) => {
    const x = i * stepX;
    const y = height - ((v - min) / range) * (height - 2) - 1;
    return [x, y];
  });
  const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const areaPath = `${path} L${pts[pts.length - 1][0]},${height} L0,${height} Z`;
  return (
    <svg className="kpi-spark" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none">
      <path d={areaPath} fill={color} opacity="0.08" />
      <path d={path} fill="none" stroke={color} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}
window.Sparkline = Sparkline;

function KpiCell({ label, value, delta, sparkData, sparkColor }) {
  return (
    <div className="kpi-cell">
      <div className="kpi-label">{label}</div>
      <div className="kpi-value tnum">{value}</div>
      {delta != null && <Delta value={delta} />}
      {sparkData && <Sparkline data={sparkData} color={sparkColor} />}
    </div>
  );
}
window.KpiCell = KpiCell;

function Toast({ toasts }) {
  return (
    <div className="toast-stack">
      {toasts.map((t) => (
        <div key={t.id} className={`toast ${t.kind || ''}`}>
          {t.kind === 'success' && <Icon name="Check" size={14} />}
          <span>{t.msg}</span>
        </div>
      ))}
    </div>
  );
}
window.Toast = Toast;

// Dropdown
function Dropdown({ trigger, children, align = 'right', direction = 'down' }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    function onDoc(e) {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    }
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);
  const menuClass = `dd-menu${direction === 'up' ? ' dd-menu-up' : ''}`;
  return (
    <div className="dropdown" ref={ref}>
      <div onClick={() => setOpen((v) => !v)}>{trigger}</div>
      {open && (
        <div className={menuClass} style={align === 'left' ? { left: 0, right: 'auto' } : null} onClick={() => setOpen(false)}>
          {children}
        </div>
      )}
    </div>
  );
}
window.Dropdown = Dropdown;

function SectionHeader({ title, desc, right }) {
  return (
    <div className="section-header">
      <div>
        <h1>{title}</h1>
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 24 }}>
        {desc && <p className="desc">{desc}</p>}
        {right}
      </div>
    </div>
  );
}
window.SectionHeader = SectionHeader;

function Modal({ children, onClose }) {
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>{children}</div>
    </div>
  );
}
window.Modal = Modal;

function SidePanel({ open, onClose, title, children }) {
  if (!open) return null;
  return (
    <React.Fragment>
      <div className="side-panel-backdrop" onClick={onClose} />
      <aside className="side-panel">
        <div className="side-panel-head">
          <div>
            <div className="card-eyebrow" style={{ margin: 0 }}>Prospect detail</div>
            <h3 className="card-title" style={{ marginTop: 6 }}>{title}</h3>
          </div>
          <button className="tlink" onClick={onClose} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            Close <Icon name="X" size={14} />
          </button>
        </div>
        <div className="side-panel-body">{children}</div>
      </aside>
    </React.Fragment>
  );
}
window.SidePanel = SidePanel;

// Range toggle (Last 7 / 30 / 90 / YTD)
function RangeToggle({ value, onChange, options = ['7D', '30D', '90D', 'YTD'] }) {
  return (
    <div className="range-toggle">
      {options.map((o) => (
        <button key={o} className={value === o ? 'active' : ''} onClick={() => onChange(o)}>{o}</button>
      ))}
    </div>
  );
}
window.RangeToggle = RangeToggle;

// Two-column section title for a tab (serif uppercase + small descriptor).
function TabHeader({ title, desc, right }) {
  return (
    <div className="section-header">
      <h1>{title}</h1>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 20 }}>
        {desc && <p className="desc">{desc}</p>}
        {right}
      </div>
    </div>
  );
}
window.TabHeader = TabHeader;

Object.assign(window, {
  Icon, Pill, Card, StatusChip, ScorePill, Delta, Sparkline, KpiCell,
  Toast, Dropdown, SectionHeader, Modal, SidePanel, RangeToggle, TabHeader,
});
