// Shared UI components and utilities

const { useState, useEffect, useMemo, useRef, useCallback, createContext, useContext, Fragment } = React;

// ---------- Icon helper (Lucide via font) ----------
const Icon = ({ name, size = 16, style, className = '' }) => (
  <i className={`lucide lucide-${name} ${className}`} style={{ fontSize: size, lineHeight: 1, display: 'inline-block', verticalAlign: 'middle', ...style }} />
);

// ---------- Button ----------
const Btn = ({ kind = 'primary', size = 'md', icon, iconRight, children, onClick, disabled, type = 'button', style, full }) => {
  const base = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
    fontWeight: 500, letterSpacing: '-0.005em',
    borderRadius: 999, transition: 'all .15s ease',
    cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.5 : 1,
    whiteSpace: 'nowrap', border: '1px solid transparent',
    width: full ? '100%' : 'auto',
  };
  const sizes = {
    sm: { padding: '6px 12px', fontSize: 13 },
    md: { padding: '10px 18px', fontSize: 14 },
    lg: { padding: '14px 24px', fontSize: 15 },
  };
  const kinds = {
    primary: { background: 'var(--accent)', color: 'white' },
    dark:    { background: 'var(--green-deep)', color: '#F5EEDE' },
    ghost:   { background: 'transparent', color: 'var(--ink)', border: '1px solid #dcd5c5' },
    ghostDark: { background: 'transparent', color: '#F5EEDE', border: '1px solid rgba(245,238,222,0.3)' },
    soft:    { background: 'rgba(232,93,47,0.12)', color: 'var(--accent)' },
    link:    { background: 'transparent', color: 'var(--accent)', padding: 0 },
  };
  return (
    <button type={type} onClick={onClick} disabled={disabled}
      onMouseEnter={e => !disabled && (e.currentTarget.style.transform = 'translateY(-1px)')}
      onMouseLeave={e => !disabled && (e.currentTarget.style.transform = 'translateY(0)')}
      style={{ ...base, ...sizes[size], ...kinds[kind], ...style }}>
      {icon && <Icon name={icon} size={size === 'sm' ? 14 : 16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size === 'sm' ? 14 : 16} />}
    </button>
  );
};

// ---------- Badge / pill ----------
const Pill = ({ tone = 'neutral', children, icon, style }) => {
  const tones = {
    neutral: { bg: '#EFEADA', fg: '#5a5544' },
    green:   { bg: 'rgba(46,92,66,0.12)', fg: 'var(--green)' },
    orange:  { bg: 'rgba(232,93,47,0.14)', fg: '#B8431F' },
    blue:    { bg: 'rgba(27,73,101,0.1)', fg: '#1B4965' },
    warn:    { bg: '#F8E7C8', fg: '#8A5A1C' },
    red:     { bg: '#F7D9D1', fg: '#9A3318' },
    white:   { bg: 'rgba(255,255,255,0.9)', fg: 'var(--ink)' },
    dark:    { bg: 'rgba(26,31,28,0.88)', fg: '#fff' },
  };
  const t = tones[tone] || tones.neutral;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '4px 10px', borderRadius: 999, background: t.bg, color: t.fg, fontSize: 12, fontWeight: 500, letterSpacing: '-0.005em', ...style }}>
      {icon && <Icon name={icon} size={12} />}
      {children}
    </span>
  );
};

// ---------- Text input ----------
const Input = ({ label, value, onChange, placeholder, type = 'text', hint, required, suffix, prefix, style }) => (
  <label style={{ display: 'block', ...style }}>
    {label && <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 6, color: '#3a3a33' }}>{label}{required && <span style={{ color: 'var(--accent)' }}> *</span>}</div>}
    <div style={{ display: 'flex', alignItems: 'center', background: 'white', border: '1px solid #e2dccb', borderRadius: 10, padding: '0 12px', transition: 'all .15s', }}>
      {prefix && <span style={{ color: '#8a8573', marginRight: 8, fontSize: 14 }}>{prefix}</span>}
      <input type={type} value={value || ''} onChange={e => onChange && onChange(e.target.value)} placeholder={placeholder}
        onFocus={e => e.currentTarget.parentElement.style.borderColor = 'var(--accent)'}
        onBlur={e => e.currentTarget.parentElement.style.borderColor = '#e2dccb'}
        style={{ flex: 1, border: 0, outline: 0, padding: '11px 0', background: 'transparent', fontSize: 14, width: '100%' }} />
      {suffix && <span style={{ color: '#8a8573', marginLeft: 8, fontSize: 14 }}>{suffix}</span>}
    </div>
    {hint && <div style={{ fontSize: 12, color: '#8a8573', marginTop: 4 }}>{hint}</div>}
  </label>
);

const Textarea = ({ label, value, onChange, placeholder, rows = 4, hint, required, style }) => (
  <label style={{ display: 'block', ...style }}>
    {label && <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 6, color: '#3a3a33' }}>{label}{required && <span style={{ color: 'var(--accent)' }}> *</span>}</div>}
    <textarea value={value || ''} onChange={e => onChange && onChange(e.target.value)} placeholder={placeholder} rows={rows}
      onFocus={e => e.currentTarget.style.borderColor = 'var(--accent)'}
      onBlur={e => e.currentTarget.style.borderColor = '#e2dccb'}
      style={{ width: '100%', border: '1px solid #e2dccb', borderRadius: 10, padding: '11px 12px', background: 'white', fontSize: 14, outline: 0, resize: 'vertical', transition: 'border-color .15s', lineHeight: 1.5 }} />
    {hint && <div style={{ fontSize: 12, color: '#8a8573', marginTop: 4 }}>{hint}</div>}
  </label>
);

const Select = ({ label, value, onChange, options, required, style }) => (
  <label style={{ display: 'block', ...style }}>
    {label && <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 6, color: '#3a3a33' }}>{label}{required && <span style={{ color: 'var(--accent)' }}> *</span>}</div>}
    <div style={{ position: 'relative', background: 'white', border: '1px solid #e2dccb', borderRadius: 10 }}>
      <select value={value || ''} onChange={e => onChange && onChange(e.target.value)}
        style={{ width: '100%', padding: '11px 36px 11px 12px', border: 0, background: 'transparent', fontSize: 14, outline: 0, appearance: 'none', cursor: 'pointer' }}>
        {options.map(o => typeof o === 'string'
          ? <option key={o} value={o}>{o}</option>
          : <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
      <Icon name="chevron-down" size={16} style={{ position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: '#8a8573' }} />
    </div>
  </label>
);

const Toggle = ({ value, onChange, label, hint }) => (
  <label style={{ display: 'flex', alignItems: 'flex-start', gap: 12, cursor: 'pointer' }}>
    <button type="button" onClick={() => onChange && onChange(!value)}
      style={{ width: 40, height: 22, borderRadius: 999, background: value ? 'var(--accent)' : '#d8d2c0', position: 'relative', transition: 'all .15s', flexShrink: 0, marginTop: 1 }}>
      <span style={{ position: 'absolute', top: 2, left: value ? 20 : 2, width: 18, height: 18, borderRadius: '50%', background: 'white', transition: 'all .15s', boxShadow: '0 1px 2px rgba(0,0,0,0.15)' }} />
    </button>
    {label && <div>
      <div style={{ fontSize: 14, fontWeight: 500 }}>{label}</div>
      {hint && <div style={{ fontSize: 12, color: '#8a8573', marginTop: 2 }}>{hint}</div>}
    </div>}
  </label>
);

// ---------- Card (placeholder image with ken-burns-feel) ----------
const Img = ({ src, alt = '', style, ratio, className }) => {
  const [loaded, setLoaded] = useState(false);
  return (
    <div style={{ position: 'relative', overflow: 'hidden', background: '#e5ddc8', aspectRatio: ratio, ...style }} className={className}>
      {!loaded && <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(135deg, #d8ceb4, #c9bf9f)' }} />}
      <img src={src} alt={alt} onLoad={() => setLoaded(true)}
        style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block', opacity: loaded ? 1 : 0, transition: 'opacity .4s' }} />
    </div>
  );
};

// ---------- Modal ----------
const Modal = ({ open, onClose, children, width = 600, title, subtitle }) => {
  useEffect(() => {
    if (!open) return;
    const onKey = e => e.key === 'Escape' && onClose && onClose();
    window.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(20,22,18,0.55)', backdropFilter: 'blur(4px)', zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20, animation: 'fadeIn .15s ease' }}>
      <style>{`@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }`}</style>
      <div onClick={e => e.stopPropagation()} style={{ background: 'white', borderRadius: 16, width: '100%', maxWidth: width, maxHeight: '90vh', overflow: 'auto', animation: 'slideUp .2s ease', boxShadow: '0 20px 60px rgba(0,0,0,0.3)' }}>
        {(title || subtitle) && (
          <div style={{ padding: '20px 24px 16px', borderBottom: '1px solid #eee7d6', position: 'sticky', top: 0, background: 'white', zIndex: 1 }}>
            <div style={{ display: 'flex', alignItems: 'start', justifyContent: 'space-between', gap: 12 }}>
              <div>
                {title && <h3 style={{ fontSize: 22, fontFamily: 'Fraunces', letterSpacing: '-0.02em' }}>{title}</h3>}
                {subtitle && <div style={{ fontSize: 13, color: '#8a8573', marginTop: 4 }}>{subtitle}</div>}
              </div>
              <button onClick={onClose} style={{ width: 32, height: 32, borderRadius: 8, display: 'grid', placeItems: 'center', color: '#666' }}>
                <Icon name="x" size={18} />
              </button>
            </div>
          </div>
        )}
        {children}
      </div>
    </div>
  );
};

// ---------- Empty / toast ----------
const useToast = () => {
  const [toast, setToast] = useState(null);
  const show = (message, tone = 'success') => {
    setToast({ message, tone, id: Date.now() });
    setTimeout(() => setToast(null), 3000);
  };
  const node = toast && (
    <div style={{ position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)', background: toast.tone === 'success' ? 'var(--green-deep)' : toast.tone === 'error' ? '#7a2716' : 'var(--ink)', color: 'white', padding: '12px 20px', borderRadius: 999, zIndex: 300, fontSize: 14, fontWeight: 500, boxShadow: '0 10px 30px rgba(0,0,0,0.25)', display: 'flex', alignItems: 'center', gap: 10, animation: 'slideUp .2s ease' }}>
      <Icon name={toast.tone === 'error' ? 'circle-x' : 'circle-check'} size={16} />
      {toast.message}
    </div>
  );
  return { show, node };
};

// ---------- Slug helper ----------
const slugify = s => (s || '').toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');

// ---------- Format ----------
const fmtMYR = n => 'RM ' + n.toLocaleString('en-MY', { maximumFractionDigits: 0 });
const fmtDate = d => {
  try {
    return new Date(d).toLocaleDateString('en-MY', { day: '2-digit', month: 'short', year: 'numeric' });
  } catch { return d; }
};
const relTime = d => {
  const diff = (Date.now() - new Date(d).getTime()) / 1000;
  if (diff < 60) return 'just now';
  if (diff < 3600) return Math.floor(diff/60) + ' min ago';
  if (diff < 86400) return Math.floor(diff/3600) + 'h ago';
  if (diff < 86400*7) return Math.floor(diff/86400) + 'd ago';
  return fmtDate(d);
};

Object.assign(window, {
  Icon, Btn, Pill, Input, Textarea, Select, Toggle, Img, Modal, useToast,
  slugify, fmtMYR, fmtDate, relTime,
  useState, useEffect, useMemo, useRef, useCallback, createContext, useContext, Fragment,
});
