// Reusable primitives: Button, Chip, Avatar, Card, etc.

const Button = ({ variant = 'primary', size = 'md', icon, iconRight, children, onClick, disabled, className = '', style = {}, as = 'button', href, type = 'button' }) => {
  const base = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: 8,
    fontFamily: 'inherit',
    fontWeight: 550,
    borderRadius: 8,
    border: '1px solid transparent',
    transition: 'all 120ms ease',
    cursor: disabled ? 'not-allowed' : 'pointer',
    opacity: disabled ? 0.5 : 1,
    whiteSpace: 'nowrap',
    userSelect: 'none',
  };
  const sizes = {
    sm: { height: 30, padding: '0 12px', fontSize: 13 },
    md: { height: 36, padding: '0 14px', fontSize: 13.5 },
    lg: { height: 44, padding: '0 18px', fontSize: 14.5 },
  };
  const variants = {
    primary: { background: 'var(--ink)', color: 'var(--bg)', borderColor: 'var(--ink)' },
    accent: { background: 'var(--accent)', color: '#fff', borderColor: 'var(--accent)' },
    secondary: { background: 'var(--bg-raised)', color: 'var(--ink)', borderColor: 'var(--line-2)' },
    ghost: { background: 'transparent', color: 'var(--ink-2)' },
    soft: { background: 'var(--bg-muted)', color: 'var(--ink-2)' },
    danger: { background: 'transparent', color: 'var(--danger)', borderColor: 'var(--line-2)' },
  };
  const props = {
    onClick: disabled ? undefined : onClick,
    disabled,
    className: `btn ${className}`,
    style: { ...base, ...sizes[size], ...variants[variant], ...style },
    type: as === 'button' ? type : undefined,
    href,
  };
  const Tag = as;
  return (
    <Tag {...props}>
      {icon && <Icon name={icon} size={size === 'sm' ? 14 : 16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size === 'sm' ? 14 : 16} />}
    </Tag>
  );
};

const Chip = ({ tone = 'neutral', children, icon, size = 'md', style = {} }) => {
  const tones = {
    neutral: { background: 'var(--bg-muted)', color: 'var(--ink-2)' },
    accent: { background: 'var(--accent-soft)', color: 'var(--accent-ink)' },
    success: { background: 'oklch(0.95 0.04 155)', color: 'oklch(0.38 0.11 155)' },
    warning: { background: 'oklch(0.95 0.06 75)', color: 'oklch(0.42 0.13 65)' },
    danger: { background: 'oklch(0.95 0.04 25)', color: 'oklch(0.42 0.15 25)' },
    indigo: { background: 'oklch(0.95 0.03 275)', color: 'oklch(0.38 0.13 275)' },
    outline: { background: 'transparent', color: 'var(--ink-2)', border: '1px solid var(--line-2)' },
    ink: { background: 'var(--ink)', color: 'var(--bg)' },
  };
  const sizes = { sm: { padding: '2px 7px', fontSize: 11, height: 20 }, md: { padding: '3px 9px', fontSize: 12, height: 24 }, lg: { padding: '5px 11px', fontSize: 13, height: 28 } };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      borderRadius: 99, fontWeight: 550, lineHeight: 1,
      letterSpacing: '-0.005em',
      ...sizes[size], ...tones[tone], ...style,
    }}>
      {icon && <Icon name={icon} size={11} />}
      {children}
    </span>
  );
};

const Avatar = ({ name = '?', src, size = 32, tone, style = {} }) => {
  const hues = [65, 20, 275, 160, 340];
  const hue = hues[(name.charCodeAt(0) + name.length) % hues.length];
  const bg = tone || `oklch(0.82 0.08 ${hue})`;
  const fg = `oklch(0.30 0.10 ${hue})`;
  const initials = name.split(' ').map(w => w[0]).slice(0, 2).join('').toUpperCase();
  return (
    <span style={{
      width: size, height: size,
      borderRadius: '50%',
      background: src ? `url(${src}) center/cover` : bg,
      color: fg,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      fontWeight: 600, fontSize: size * 0.38,
      flexShrink: 0,
      ...style,
    }}>
      {!src && initials}
    </span>
  );
};

// Placeholder image — subtly striped SVG (system prompt spec)
const Placeholder = ({ label = 'image', aspect = '16/9', style = {}, hue = 65, rounded = 10 }) => {
  const svg = `
    <svg xmlns='http://www.w3.org/2000/svg' width='400' height='225' preserveAspectRatio='none'>
      <defs>
        <pattern id='s' width='16' height='16' patternUnits='userSpaceOnUse' patternTransform='rotate(45)'>
          <rect width='16' height='16' fill='oklch(0.92 0.04 ${hue})'/>
          <rect width='8' height='16' fill='oklch(0.88 0.05 ${hue})'/>
        </pattern>
      </defs>
      <rect width='100%' height='100%' fill='url(%23s)'/>
    </svg>`.replace(/#/g, '%23').replace(/\s+/g, ' ');
  return (
    <div style={{
      aspectRatio: aspect,
      background: `url("data:image/svg+xml;utf8,${svg}")`,
      backgroundSize: 'cover',
      borderRadius: rounded,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: 'var(--font-mono)', fontSize: 11, color: `oklch(0.35 0.10 ${hue})`,
      letterSpacing: '0.04em', textTransform: 'uppercase',
      position: 'relative',
      ...style,
    }}>
      {label}
    </div>
  );
};

const Card = ({ children, pad = 20, style = {}, className = '', onClick, hover }) => (
  <div
    onClick={onClick}
    className={className}
    style={{
      background: 'var(--bg-raised)',
      border: '1px solid var(--line)',
      borderRadius: 14,
      padding: pad,
      cursor: onClick ? 'pointer' : 'default',
      transition: 'all 140ms',
      ...(hover ? {} : {}),
      ...style,
    }}
  >{children}</div>
);

const Divider = ({ vertical, style = {} }) => (
  <div style={vertical ? { width: 1, alignSelf: 'stretch', background: 'var(--line)', ...style } : { height: 1, background: 'var(--line)', ...style }} />
);

// Form inputs
const Field = ({ label, hint, error, children, right, style = {} }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 6, ...style }}>
    {label && <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
      <label style={{ fontSize: 12.5, fontWeight: 550, color: 'var(--ink-2)' }}>{label}</label>
      {right}
    </div>}
    {children}
    {hint && !error && <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{hint}</div>}
    {error && <div style={{ fontSize: 11.5, color: 'var(--danger)' }}>{error}</div>}
  </div>
);

const Input = React.forwardRef(({ prefix, suffix, style = {}, value, defaultValue, onChange, ...rest }, ref) => {
  // If caller passes `value` without `onChange`, treat it as display-only default so React doesn't warn and blank the input.
  const isControlled = onChange != null;
  const valueProps = isControlled
    ? { value, onChange }
    : { defaultValue: value != null ? value : defaultValue };
  return (
  <div style={{
    display: 'flex', alignItems: 'center', gap: 8,
    border: '1px solid var(--line-2)', background: 'var(--bg-raised)',
    borderRadius: 8, padding: '0 12px', height: 38, ...style,
  }}>
    {prefix && <span style={{ color: 'var(--ink-3)', fontSize: 13, display: 'flex', alignItems: 'center' }}>{prefix}</span>}
    <input ref={ref} {...rest} {...valueProps} style={{
      flex: 1, border: 0, outline: 0, background: 'transparent',
      fontFamily: 'inherit', fontSize: 14, color: 'var(--ink)', height: '100%',
      minWidth: 0,
    }} />
    {suffix && <span style={{ color: 'var(--ink-3)', fontSize: 12 }}>{suffix}</span>}
  </div>
  );
});

const Textarea = ({ style = {}, rows = 3, value, defaultValue, onChange, ...rest }) => {
  const isControlled = onChange != null;
  const valueProps = isControlled
    ? { value, onChange }
    : { defaultValue: value != null ? value : defaultValue };
  return (
    <textarea rows={rows} {...rest} {...valueProps} style={{
    border: '1px solid var(--line-2)', background: 'var(--bg-raised)',
    borderRadius: 8, padding: '10px 12px',
    fontFamily: 'inherit', fontSize: 14, color: 'var(--ink)',
    outline: 0, resize: 'vertical', ...style,
  }} />
  );
};

const Toggle = ({ checked, onChange, label, desc }) => (
  <label style={{ display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer' }}>
    <span
      onClick={e => { e.preventDefault(); onChange?.(!checked); }}
      style={{
        width: 36, height: 20, borderRadius: 99, position: 'relative',
        background: checked ? 'var(--accent)' : 'var(--line-2)',
        transition: 'background 150ms', flexShrink: 0,
      }}>
      <span style={{
        position: 'absolute', top: 2, left: checked ? 18 : 2,
        width: 16, height: 16, borderRadius: '50%', background: '#fff',
        transition: 'left 180ms cubic-bezier(0.2, 0.9, 0.3, 1)',
        boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
      }}/>
    </span>
    {(label || desc) && <span style={{ display: 'flex', flexDirection: 'column' }}>
      {label && <span style={{ fontSize: 13.5, fontWeight: 500 }}>{label}</span>}
      {desc && <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>{desc}</span>}
    </span>}
  </label>
);

const Select = ({ value, onChange, options, placeholder, style = {} }) => (
  <div style={{
    position: 'relative',
    border: '1px solid var(--line-2)', background: 'var(--bg-raised)',
    borderRadius: 8, height: 38, ...style,
  }}>
    <select
      value={value || ''}
      onChange={e => onChange?.(e.target.value)}
      style={{
        appearance: 'none', width: '100%', height: '100%',
        border: 0, outline: 0, background: 'transparent',
        fontFamily: 'inherit', fontSize: 14, color: value ? 'var(--ink)' : 'var(--ink-3)',
        padding: '0 34px 0 12px',
      }}
    >
      {placeholder && <option value="">{placeholder}</option>}
      {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
    </select>
    <Icon name="chevronDown" size={16} style={{ position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', pointerEvents: 'none' }} />
  </div>
);

const SegControl = ({ value, onChange, options, fullWidth }) => (
  <div style={{
    display: 'inline-flex', background: 'var(--bg-sunken)',
    borderRadius: 8, padding: 3, gap: 2,
    width: fullWidth ? '100%' : 'auto',
  }}>
    {options.map(o => (
      <button
        key={o.value}
        onClick={() => onChange?.(o.value)}
        style={{
          flex: fullWidth ? 1 : 'initial',
          padding: '6px 12px', border: 0, borderRadius: 6,
          background: value === o.value ? 'var(--bg-raised)' : 'transparent',
          color: value === o.value ? 'var(--ink)' : 'var(--ink-3)',
          fontSize: 12.5, fontWeight: 550,
          boxShadow: value === o.value ? '0 1px 2px rgba(0,0,0,0.06)' : 'none',
          transition: 'all 140ms',
          display: 'inline-flex', alignItems: 'center', gap: 6, justifyContent: 'center',
        }}
      >
        {o.icon && <Icon name={o.icon} size={14} />}
        {o.label}
      </button>
    ))}
  </div>
);

const Tabs = ({ value, onChange, options, style = {} }) => (
  <div style={{
    display: 'flex', gap: 4, borderBottom: '1px solid var(--line)',
    ...style,
  }}>
    {options.map(o => (
      <button
        key={o.value}
        onClick={() => onChange?.(o.value)}
        style={{
          padding: '10px 14px', border: 0, background: 'transparent',
          fontFamily: 'inherit', fontSize: 13.5, fontWeight: 550,
          color: value === o.value ? 'var(--ink)' : 'var(--ink-3)',
          borderBottom: `2px solid ${value === o.value ? 'var(--ink)' : 'transparent'}`,
          marginBottom: -1, cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', gap: 8,
        }}
      >
        {o.label}
        {o.count != null && <span style={{
          background: value === o.value ? 'var(--ink)' : 'var(--bg-muted)',
          color: value === o.value ? 'var(--bg)' : 'var(--ink-3)',
          padding: '1px 7px', borderRadius: 99, fontSize: 11, fontWeight: 600,
        }}>{o.count}</span>}
      </button>
    ))}
  </div>
);

const Stat = ({ label, value, delta, tone = 'neutral', sub, icon }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
    <div style={{ fontSize: 12, color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 6, fontWeight: 500 }}>
      {icon && <Icon name={icon} size={14} />}
      {label}
    </div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
      <div style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', fontFamily: 'var(--font-display)' }}>{value}</div>
      {delta && <span style={{ fontSize: 12, color: delta.startsWith('-') ? 'var(--danger)' : 'var(--success)', fontWeight: 600 }}>{delta}</span>}
    </div>
    {sub && <div style={{ fontSize: 11.5, color: 'var(--ink-4)' }}>{sub}</div>}
  </div>
);

// Tiny sparkline (SVG, data array 0-100)
const Sparkline = ({ data, color, width = 120, height = 36, area = true }) => {
  const max = Math.max(...data, 1); const min = Math.min(...data, 0);
  const range = (max - min) || 1;
  const points = data.map((v, i) => `${(i / (data.length - 1)) * width},${height - ((v - min) / range) * height}`);
  const path = `M${points.join(' L')}`;
  const areaPath = `${path} L${width},${height} L0,${height} Z`;
  const c = color || 'var(--accent)';
  return (
    <svg width={width} height={height} style={{ display: 'block' }}>
      {area && <path d={areaPath} fill={c} opacity="0.12" />}
      <path d={path} fill="none" stroke={c} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
};

// Toasts (very light, optional)
const Toast = ({ icon = 'check', title, desc }) => (
  <div style={{
    background: 'var(--bg-raised)', border: '1px solid var(--line-2)',
    borderRadius: 12, padding: '10px 14px', boxShadow: 'var(--shadow-md)',
    display: 'flex', alignItems: 'center', gap: 12, minWidth: 260,
    animation: 'slideInRight 300ms cubic-bezier(0.2, 0.9, 0.3, 1)',
  }}>
    <span style={{
      width: 28, height: 28, borderRadius: 99,
      background: 'var(--accent-soft)', color: 'var(--accent-ink)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}><Icon name={icon} size={16} /></span>
    <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
      <div style={{ fontSize: 13, fontWeight: 600 }}>{title}</div>
      {desc && <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{desc}</div>}
    </div>
  </div>
);

// Kbd
const Kbd = ({ children }) => (
  <kbd style={{
    fontFamily: 'var(--font-mono)', fontSize: 10.5,
    padding: '2px 6px', border: '1px solid var(--line-2)',
    borderBottomWidth: 2, borderRadius: 4,
    background: 'var(--bg-raised)', color: 'var(--ink-2)',
  }}>{children}</kbd>
);

Object.assign(window, { Button, Chip, Avatar, Placeholder, Card, Divider, Field, Input, Textarea, Toggle, Select, SegControl, Tabs, Stat, Sparkline, Toast, Kbd });
