// shared.jsx — Shoplix shared UI primitives
// Exports: Button, Card, KPICard, StatusPill, Badge, Input, Select, Textarea,
//          Toggle, Modal, EmptyState, Spinner, ProgressBar, Tabs, SectionTitle, Tooltip

// Icon — React-native SVG icons (avoids Lucide DOM mutation crashes in dynamic components)
const ICON_PATHS = {
  'grip-vertical':    '<circle cx="9" cy="5" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="19" r="1"/>',
  'lock':             '<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
  'chevron-up':       '<path d="m18 15-6-6-6 6"/>',
  'chevron-down':     '<path d="m6 9 6 6 6-6"/>',
  'mouse-pointer-2':  '<path d="m4 4 7.07 17 2.51-7.39L21 11.07z"/>',
  'check-circle':     '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/>',
  'image-plus':       '<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"/><line x1="16" x2="22" y1="5" y2="5"/><line x1="19" x2="19" y1="2" y2="8"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>',
  'image':            '<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>',
  'grid':             '<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>',
  'layout-grid':      '<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>',
  'megaphone':        '<path d="m3 11 18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/>',
  'star':             '<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>',
  'layout-dashboard': '<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>',
  'shield-check':     '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="m9 12 2 2 4-4"/>',
  'save':             '<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/>',
  'check':            '<path d="M20 6 9 17l-5-5"/>',
  'eye':              '<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/>',
  'plus':             '<path d="M5 12h14"/><path d="M12 5v14"/>',
  'shield':           '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
  'x':                '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
  'arrow-right':      '<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',
};
const Icon = ({ name, size = 16, style = {} }) => {
  const path = ICON_PATHS[name];
  if (!path) {
    // Fallback: still use Lucide for icons not in the list (only safe in static/non-re-rendering contexts)
    return <i data-lucide={name} style={{ width: size, height: size, display: 'inline-block', flexShrink: 0, ...style }}></i>;
  }
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"
      style={{ display: 'inline-block', flexShrink: 0, ...style }}
      dangerouslySetInnerHTML={{ __html: path }} />
  );
};

const Button = ({ children, variant = 'primary', size = 'md', icon, iconRight, onClick, disabled, style = {} }) => {
  const [pressed, setPressed] = React.useState(false);
  const [hovered, setHovered] = React.useState(false);

  const base = {
    fontFamily: 'var(--font-ui)', fontWeight: 500,
    fontSize: size === 'sm' ? '12px' : size === 'lg' ? '15px' : '14px',
    lineHeight: size === 'sm' ? '16px' : '20px',
    padding: size === 'sm' ? '6px 12px' : size === 'lg' ? '13px 28px' : '9px 18px',
    borderRadius: size === 'sm' ? '8px' : '10px',
    border: '1px solid transparent',
    cursor: disabled ? 'not-allowed' : 'pointer',
    display: 'inline-flex', alignItems: 'center', gap: '7px',
    transition: 'all 180ms cubic-bezier(0.2,0.8,0.2,1)',
    whiteSpace: 'nowrap', userSelect: 'none', textDecoration: 'none',
    transform: pressed ? 'scale(0.98)' : 'scale(1)',
    opacity: disabled ? 0.45 : 1, flexShrink: 0, ...style,
  };

  const v = {
    primary: { background: hovered ? 'var(--honey-hover)' : 'var(--honey)', color: 'var(--ink)' },
    secondary: { background: hovered ? 'var(--ink-04)' : 'transparent', borderColor: 'var(--hairline-bold)', color: 'var(--fg-1)' },
    ghost: { background: 'transparent', color: 'var(--fg-1)', textDecoration: hovered ? 'underline' : 'none' },
    destructive: { background: 'transparent', borderColor: 'var(--ruby)', color: 'var(--ruby)' },
    danger: { background: 'var(--ruby)', color: '#fff' },
    ink: { background: 'var(--ink)', color: 'var(--paper)' },
  };

  const iconSz = size === 'sm' ? 13 : 15;
  return (
    <button style={{ ...base, ...v[variant] }} onClick={disabled ? undefined : onClick}
      onMouseDown={() => !disabled && setPressed(true)} onMouseUp={() => setPressed(false)}
      onMouseLeave={() => { setPressed(false); setHovered(false); }} onMouseEnter={() => setHovered(true)}
      disabled={disabled}>
      {icon && <i data-lucide={icon} style={{ width: iconSz, height: iconSz, flexShrink: 0 }}></i>}
      {children}
      {iconRight && <i data-lucide={iconRight} style={{ width: iconSz, height: iconSz, flexShrink: 0 }}></i>}
    </button>
  );
};

const IconButton = ({ icon, onClick, size = 32, title, active = false }) => (
  <button onClick={onClick} title={title} style={{
    width: size, height: size, borderRadius: 8, border: '1px solid transparent',
    background: active ? 'var(--ink-08)' : 'transparent', cursor: 'pointer',
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    color: 'var(--fg-2)', transition: 'all 180ms var(--ease)',
  }}
    onMouseEnter={e => e.currentTarget.style.background = 'var(--ink-08)'}
    onMouseLeave={e => e.currentTarget.style.background = active ? 'var(--ink-08)' : 'transparent'}>
    <i data-lucide={icon} style={{ width: 16, height: 16 }}></i>
  </button>
);

const StatusPill = ({ status }) => {
  const cfg = {
    live:       { bg: 'var(--mint-tint)',    fg: '#143830', dot: 'var(--mint)',    label: 'Live' },
    active:     { bg: 'var(--mint-tint)',    fg: '#143830', dot: 'var(--mint)',    label: 'Active' },
    synced:     { bg: 'var(--mint-tint)',    fg: '#143830', dot: 'var(--mint)',    label: 'Synced' },
    scheduled:  { bg: 'var(--honey-tint)',   fg: '#8B5A2B', dot: 'var(--honey)',   label: 'Scheduled' },
    trialing:   { bg: 'var(--honey-tint)',   fg: '#8B5A2B', dot: 'var(--honey)',   label: 'Trialing' },
    draft:      { bg: 'var(--sand-50)',      fg: 'var(--fg-2)', dot: 'var(--ink-40)', label: 'Draft' },
    paused:     { bg: 'var(--sand-50)',      fg: 'var(--fg-2)', dot: 'var(--ink-40)', label: 'Paused' },
    'in review':{ bg: 'var(--amber-tint)',   fg: '#5E4307', dot: 'var(--amber)',   label: 'In review' },
    past_due:   { bg: 'var(--amber-tint)',   fg: '#5E4307', dot: 'var(--amber)',   label: 'Past due' },
    rejected:   { bg: 'var(--ruby-tint)',    fg: '#7A1D0B', dot: 'var(--ruby)',    label: 'Rejected' },
    error:      { bg: 'var(--ruby-tint)',    fg: '#7A1D0B', dot: 'var(--ruby)',    label: 'Error' },
    cancelled:  { bg: 'var(--sand-100)',     fg: 'var(--fg-3)', dot: 'var(--ink-20)', label: 'Cancelled' },
    sent:       { bg: 'var(--mint-tint)',    fg: '#143830', dot: 'var(--mint)',    label: 'Sent' },
    building:   { bg: 'var(--honey-tint)',   fg: '#8B5A2B', dot: 'var(--honey)',   label: 'Building' },
  };
  const c = cfg[status?.toLowerCase()] || cfg.draft;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 9px 3px 7px', borderRadius: 999, background: c.bg, color: c.fg, fontSize: 11, fontWeight: 500, whiteSpace: 'nowrap' }}>
      <span style={{ width: 6, height: 6, borderRadius: '50%', background: c.dot, flexShrink: 0 }}></span>
      {c.label}
    </span>
  );
};

const Card = ({ children, style = {}, onClick, padding = 24 }) => (
  <div onClick={onClick} style={{
    background: 'var(--white)', borderRadius: 10, border: '1px solid var(--hairline)',
    padding, cursor: onClick ? 'pointer' : 'default', ...style,
  }}>
    {children}
  </div>
);

const KPICard = ({ label, value, delta, deltaDir = 'up', sub, editorial = false }) => (
  <Card style={{ flex: 1, minWidth: 160 }}>
    <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 500, marginBottom: 8 }}>{label}</div>
    <div style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 38, lineHeight: 1, letterSpacing: '-0.02em', color: editorial ? 'var(--honey)' : 'var(--ink)', marginBottom: 6 }}>{value}</div>
    {delta && <div style={{ fontSize: 12, color: deltaDir === 'up' ? 'var(--mint)' : 'var(--ruby)', fontWeight: 500 }}>{deltaDir === 'up' ? '↗' : '↘'} {delta}</div>}
    {sub && <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>{sub}</div>}
  </Card>
);

const Input = ({ label, value, onChange, placeholder, help, error, prefix, type = 'text', style = {}, readOnly }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
    {label && <label style={{ fontSize: 12, fontWeight: 500, color: 'var(--fg-2)' }}>{label}</label>}
    <div style={{ display: 'flex', background: 'var(--white)', border: `1px solid ${error ? 'var(--ruby)' : 'var(--hairline)'}`, borderRadius: 6, overflow: 'hidden', ...style }}>
      {prefix && <span style={{ padding: '9px 12px', background: 'var(--sand-50)', borderRight: '1px solid var(--hairline)', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--fg-2)', whiteSpace: 'nowrap' }}>{prefix}</span>}
      <input type={type} value={value} onChange={onChange || (() => {})} readOnly={readOnly || (!onChange && value !== undefined)} placeholder={placeholder} style={{ flex: 1, border: 0, padding: '9px 12px', fontFamily: 'var(--font-ui)', fontSize: 14, color: 'var(--ink)', background: 'transparent', outline: 'none', minWidth: 0 }} />
    </div>
    {(help || error) && <div style={{ fontSize: 11, color: error ? 'var(--ruby)' : 'var(--fg-3)' }}>{error || help}</div>}
  </div>
);

const Select = ({ label, value, onChange, options = [], style = {} }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
    {label && <label style={{ fontSize: 12, fontWeight: 500, color: 'var(--fg-2)' }}>{label}</label>}
    <select value={value} onChange={onChange} style={{ background: 'var(--white)', border: '1px solid var(--hairline)', borderRadius: 6, padding: '9px 12px', fontFamily: 'var(--font-ui)', fontSize: 14, color: 'var(--ink)', appearance: 'none', backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1l5 5 5-5' fill='none' stroke='%231A1A1A' stroke-width='1.5'/></svg>")`, backgroundRepeat: 'no-repeat', backgroundPosition: 'right 12px center', paddingRight: 32, cursor: 'pointer', ...style }}>
      {options.map(o => <option key={o.value || o} value={o.value || o}>{o.label || o}</option>)}
    </select>
  </div>
);

const Textarea = ({ label, value, onChange, placeholder, rows = 3, help }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
    {label && <label style={{ fontSize: 12, fontWeight: 500, color: 'var(--fg-2)' }}>{label}</label>}
    <textarea value={value} onChange={onChange} placeholder={placeholder} rows={rows}
      style={{ background: 'var(--white)', border: '1px solid var(--hairline)', borderRadius: 6, padding: '9px 12px', fontFamily: 'var(--font-ui)', fontSize: 14, color: 'var(--ink)', resize: 'vertical', outline: 'none', lineHeight: 1.55 }} />
    {help && <div style={{ fontSize: 11, color: 'var(--fg-3)' }}>{help}</div>}
  </div>
);

const Toggle = ({ checked, onChange, label }) => (
  <label style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', userSelect: 'none' }}>
    <div onClick={() => onChange(!checked)} style={{ width: 36, height: 20, borderRadius: 999, background: checked ? 'var(--ink)' : 'var(--sand-200)', position: 'relative', transition: 'background 200ms var(--ease)', flexShrink: 0 }}>
      <div style={{ position: 'absolute', top: 3, left: checked ? 19 : 3, width: 14, height: 14, borderRadius: '50%', background: checked ? 'var(--honey)' : 'var(--white)', transition: 'left 200ms var(--ease)' }}></div>
    </div>
    {label && <span style={{ fontSize: 13, color: 'var(--fg-1)' }}>{label}</span>}
  </label>
);

const ProgressBar = ({ value, max = 100, color = 'var(--honey)', height = 6 }) => {
  const pct = Math.min(100, Math.round((value / max) * 100));
  const barColor = pct >= 100 ? 'var(--ruby)' : pct >= 80 ? 'var(--amber)' : color;
  return (
    <div style={{ height, borderRadius: 999, background: 'var(--sand-100)', overflow: 'hidden' }}>
      <div style={{ height: '100%', width: `${pct}%`, borderRadius: 999, background: barColor, transition: 'width 600ms var(--ease)' }}></div>
    </div>
  );
};

const Tabs = ({ tabs, active, onSelect }) => (
  <div style={{ display: 'flex', gap: 0, borderBottom: '1px solid var(--hairline)', marginBottom: 24 }}>
    {tabs.map(t => (
      <button key={t.id} onClick={() => onSelect(t.id)} style={{
        padding: '10px 16px', fontSize: 13, fontWeight: active === t.id ? 500 : 400,
        color: active === t.id ? 'var(--ink)' : 'var(--fg-2)',
        background: 'transparent', border: 'none', borderBottom: active === t.id ? '2px solid var(--ink)' : '2px solid transparent',
        cursor: 'pointer', marginBottom: -1, transition: 'all 180ms var(--ease)', whiteSpace: 'nowrap',
      }}>
        {t.label}
        {t.badge && <span style={{ marginLeft: 6, background: 'var(--honey)', color: 'var(--ink)', borderRadius: 999, fontSize: 10, fontWeight: 600, padding: '1px 6px' }}>{t.badge}</span>}
      </button>
    ))}
  </div>
);

const Modal = ({ open, onClose, title, children, width = 560 }) => {
  if (!open) return null;
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(26,26,26,0.4)' }}></div>
      <div style={{ position: 'relative', background: 'var(--white)', borderRadius: 16, width: `min(${width}px, calc(100vw - 48px))`, maxHeight: 'calc(100vh - 80px)', overflow: 'auto', boxShadow: 'var(--shadow-modal)' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '20px 24px', borderBottom: '1px solid var(--hairline)', position: 'sticky', top: 0, background: 'var(--white)', zIndex: 1 }}>
          <span style={{ fontWeight: 600, fontSize: 15, color: 'var(--ink)' }}>{title}</span>
          <IconButton icon="x" onClick={onClose} />
        </div>
        <div style={{ padding: 24 }}>{children}</div>
      </div>
    </div>
  );
};

const EmptyState = ({ icon = 'inbox', title, description, action }) => (
  <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: '64px 24px', gap: 12, textAlign: 'center' }}>
    <div style={{ width: 48, height: 48, background: 'var(--sand-50)', borderRadius: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--fg-3)' }}>
      <i data-lucide={icon} style={{ width: 22, height: 22 }}></i>
    </div>
    <div style={{ fontWeight: 500, fontSize: 15, color: 'var(--fg-1)' }}>{title}</div>
    {description && <div style={{ fontSize: 13, color: 'var(--fg-3)', maxWidth: 320 }}>{description}</div>}
    {action && <div style={{ marginTop: 8 }}>{action}</div>}
  </div>
);

const Spinner = ({ size = 20, color = 'var(--ink)' }) => (
  <div style={{ width: size, height: size, border: `2px solid var(--sand-100)`, borderTopColor: color, borderRadius: '50%', animation: 'spin 0.7s linear infinite' }}></div>
);

const SectionTitle = ({ eyebrow, title, action }) => (
  <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 16, gap: 16 }}>
    <div>
      {eyebrow && <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 500, marginBottom: 4 }}>{eyebrow}</div>}
      {title && <div style={{ fontSize: 16, fontWeight: 600, color: 'var(--fg-1)' }}>{title}</div>}
    </div>
    {action && <div style={{ flexShrink: 0 }}>{action}</div>}
  </div>
);

const FilterPills = ({ options, active, onSelect }) => (
  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
    {options.map(o => (
      <button key={o} onClick={() => onSelect(o)} style={{
        padding: '5px 12px', borderRadius: 999, fontSize: 12, fontWeight: 500,
        background: active === o ? 'var(--ink)' : 'var(--white)',
        color: active === o ? 'var(--paper)' : 'var(--fg-1)',
        border: `1px solid ${active === o ? 'var(--ink)' : 'var(--hairline)'}`,
        cursor: 'pointer', transition: 'all 150ms var(--ease)',
      }}>{o}</button>
    ))}
  </div>
);

Object.assign(window, { Button, IconButton, StatusPill, Card, KPICard, Input, Select, Textarea, Toggle, ProgressBar, Tabs, Modal, EmptyState, Spinner, SectionTitle, FilterPills });
