// ui.jsx — shared primitives for Credeo, exported to window
const { useState, useRef, useEffect } = React;

/* ---------- brand ---------- */
function Logo({ size = 22, mono = false }) {
  const c = mono ? 'currentColor' : 'var(--brand)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: size * 0.42 }}>
      <span style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
        <span style={{ position: 'absolute', inset: 0, border: `2px solid ${c}`, borderRadius: size * 0.28 }} />
        <span style={{ position: 'absolute', inset: size * 0.26, background: c, borderRadius: size * 0.12 }} />
      </span>
      <span style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: size * 0.92, letterSpacing: '0.01em', color: mono ? 'currentColor' : 'var(--ink)' }}>
        Credeo
      </span>
    </div>
  );
}

/* ---------- buttons ---------- */
function Button({ children, variant = 'primary', size = 'md', icon, iconRight, full, onClick, disabled, type = 'button', style }) {
  const [h, setH] = useState(false);
  const sizes = {
    sm: { padding: '7px 13px', fontSize: 13.5, gap: 7, h: 34 },
    md: { padding: '10px 17px', fontSize: 14.5, gap: 8, h: 42 },
    lg: { padding: '13px 22px', fontSize: 15.5, gap: 9, h: 50 },
  }[size];
  const variants = {
    primary: { background: h ? 'var(--brand-ink)' : 'var(--brand)', color: '#fff', border: '1px solid transparent', boxShadow: h ? 'var(--shadow-md)' : 'var(--shadow-sm)' },
    outline: { background: h ? 'var(--surface-2)' : 'var(--surface)', color: 'var(--ink)', border: '1px solid var(--line-2)' },
    ghost:   { background: h ? 'var(--surface-2)' : 'transparent', color: 'var(--ink)', border: '1px solid transparent' },
    soft:    { background: h ? 'var(--brand)' : 'var(--brand-soft)', color: h ? '#fff' : 'var(--brand-ink)', border: '1px solid transparent' },
    danger:  { background: h ? 'var(--danger)' : 'transparent', color: h ? '#fff' : 'var(--danger)', border: '1px solid var(--danger)' },
  }[variant];
  return (
    <button type={type} onClick={onClick} disabled={disabled}
      onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        gap: sizes.gap, padding: sizes.padding, fontSize: sizes.fontSize, minHeight: sizes.h,
        fontWeight: 600, fontFamily: 'var(--font-body)', borderRadius: 'var(--r-sm)',
        cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.5 : 1,
        width: full ? '100%' : 'auto', transition: 'all .16s ease', whiteSpace: 'nowrap',
        ...variants, ...style,
      }}>
      {icon && <Icon name={icon} size={sizes.fontSize + 2} stroke={2.1} />}
      {children}
      {iconRight && <Icon name={iconRight} size={sizes.fontSize + 2} stroke={2.1} />}
    </button>
  );
}

/* ---------- status + badges ---------- */
const STATUS_TONE = {
  'Pending':   { bg: 'color-mix(in srgb, var(--warn) 14%, transparent)', fg: 'var(--warn)', dot: 'var(--warn)' },
  'In review': { bg: 'color-mix(in srgb, var(--accent) 16%, transparent)', fg: 'var(--brand-ink)', dot: 'var(--accent)' },
  'Approved':  { bg: 'color-mix(in srgb, var(--ok) 14%, transparent)', fg: 'var(--ok)', dot: 'var(--ok)' },
  'Scheduled': { bg: 'var(--brand-soft)', fg: 'var(--brand-ink)', dot: 'var(--brand)' },
  'Completed': { bg: 'color-mix(in srgb, var(--ink-2) 12%, transparent)', fg: 'var(--ink-2)', dot: 'var(--ink-2)' },
  'Declined':  { bg: 'color-mix(in srgb, var(--danger) 12%, transparent)', fg: 'var(--danger)', dot: 'var(--danger)' },
};
function StatusPill({ status, size = 'md' }) {
  const t = STATUS_TONE[status] || STATUS_TONE['Pending'];
  const s = size === 'sm' ? { fs: 11.5, pad: '3px 9px 3px 7px', dot: 5 } : { fs: 12.5, pad: '5px 11px 5px 9px', dot: 6 };
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, background: t.bg, color: t.fg, padding: s.pad, borderRadius: 99, fontSize: s.fs, fontWeight: 600, letterSpacing: '0.01em' }}>
      <span style={{ width: s.dot, height: s.dot, borderRadius: 99, background: t.dot }} />
      {status}
    </span>
  );
}
function Tag({ children, tone = 'neutral' }) {
  const tones = {
    neutral: { bg: 'var(--surface-2)', fg: 'var(--ink-2)', bd: 'var(--line)' },
    brand:   { bg: 'var(--brand-soft)', fg: 'var(--brand-ink)', bd: 'transparent' },
    gold:    { bg: 'color-mix(in srgb, var(--gold) 14%, transparent)', fg: 'var(--gold)', bd: 'transparent' },
  }[tone];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: tones.bg, color: tones.fg, border: `1px solid ${tones.bd}`, padding: '4px 9px', borderRadius: 99, fontSize: 11.5, fontWeight: 600, letterSpacing: '0.02em' }}>
      {children}
    </span>
  );
}

/* ---------- avatar ---------- */
function Avatar({ name, size = 38, tone }) {
  const initials = (name || '?').split(' ').map(w => w[0]).slice(0, 2).join('').toUpperCase();
  const hue = tone ?? ([...(name||'')].reduce((a, c) => a + c.charCodeAt(0), 0) % 360);
  return (
    <span style={{
      width: size, height: size, flexShrink: 0, borderRadius: '50%',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      fontSize: size * 0.36, fontWeight: 600, fontFamily: 'var(--font-body)',
      background: `oklch(0.92 0.05 ${hue})`, color: `oklch(0.42 0.09 ${hue})`,
    }}>{initials}</span>
  );
}

/* ---------- property image placeholder (CSS-rendered, labelled) ---------- */
function PropImage({ hue = 158, label = 'property photo', radius = 'var(--r)', height = 200, tag, saved, onSave, children }) {
  return (
    <div style={{
      position: 'relative', height, borderRadius: radius, overflow: 'hidden',
      background: `linear-gradient(135deg, oklch(0.62 0.07 ${hue}) 0%, oklch(0.42 0.06 ${hue}) 100%)`,
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,.06) 0 2px, transparent 2px 11px)',
      }} />
      <div style={{
        position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 7, color: 'rgba(255,255,255,.82)',
          fontFamily: 'var(--font-mono)', fontSize: 11.5, letterSpacing: '0.04em',
          background: 'rgba(0,0,0,.18)', padding: '5px 11px', borderRadius: 99, backdropFilter: 'blur(2px)',
        }}>
          <Icon name="camera" size={13} stroke={2} /> {label}
        </span>
      </div>
      {tag && <div style={{ position: 'absolute', top: 12, left: 12 }}><Tag tone="gold">{tag}</Tag></div>}
      {onSave && (
        <button onClick={(e) => { e.stopPropagation(); onSave(); }} aria-label="Save"
          style={{
            position: 'absolute', top: 12, right: 12, width: 38, height: 38, borderRadius: '50%',
            border: 'none', cursor: 'pointer', display: 'grid', placeItems: 'center',
            background: saved ? 'var(--brand)' : 'rgba(255,255,255,.92)', color: saved ? '#fff' : 'var(--ink)',
            boxShadow: 'var(--shadow-sm)', transition: 'all .16s',
          }}>
          <Icon name="heart" size={18} fill={saved ? 'current' : 'none'} stroke={2.1} />
        </button>
      )}
      {children}
    </div>
  );
}

/* ---------- card ---------- */
function Card({ children, pad = true, hover, onClick, style }) {
  const [h, setH] = useState(false);
  return (
    <div onClick={onClick}
      onMouseEnter={() => hover && setH(true)} onMouseLeave={() => hover && setH(false)}
      style={{
        background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 'var(--r)',
        padding: pad ? 'var(--pad)' : 0, boxShadow: h ? 'var(--shadow-md)' : 'var(--shadow-sm)',
        transition: 'all .18s ease', cursor: onClick ? 'pointer' : 'default',
        transform: h ? 'translateY(-2px)' : 'none', ...style,
      }}>
      {children}
    </div>
  );
}

/* ---------- form fields ---------- */
function Field({ label, hint, children, required }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
      {label && <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>{label}{required && <span style={{ color: 'var(--danger)' }}> *</span>}</span>}
      {children}
      {hint && <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>{hint}</span>}
    </label>
  );
}
const inputStyle = {
  width: '100%', padding: '11px 13px', fontSize: 14.5, fontFamily: 'var(--font-body)',
  color: 'var(--ink)', background: 'var(--surface-2)', border: '1px solid var(--line-2)',
  borderRadius: 'var(--r-sm)', outline: 'none', transition: 'border-color .15s, box-shadow .15s',
};
function Input(props) {
  const [f, setF] = useState(false);
  return <input {...props} onFocus={() => setF(true)} onBlur={() => setF(false)}
    style={{ ...inputStyle, borderColor: f ? 'var(--brand)' : 'var(--line-2)', boxShadow: f ? '0 0 0 3px var(--brand-soft)' : 'none', ...props.style }} />;
}
function Textarea(props) {
  const [f, setF] = useState(false);
  return <textarea {...props} onFocus={() => setF(true)} onBlur={() => setF(false)} rows={props.rows || 4}
    style={{ ...inputStyle, resize: 'vertical', lineHeight: 1.5, borderColor: f ? 'var(--brand)' : 'var(--line-2)', boxShadow: f ? '0 0 0 3px var(--brand-soft)' : 'none', ...props.style }} />;
}
function Select({ options, value, onChange, style }) {
  return (
    <div style={{ position: 'relative' }}>
      <select value={value} onChange={(e) => onChange(e.target.value)}
        style={{ ...inputStyle, appearance: 'none', cursor: 'pointer', paddingRight: 36, ...style }}>
        {options.map(o => <option key={o.value ?? o} value={o.value ?? o}>{o.label ?? o}</option>)}
      </select>
      <span style={{ position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: 'var(--ink-2)' }}>
        <Icon name="chevronDown" size={16} />
      </span>
    </div>
  );
}

/* ---------- tabs ---------- */
function Segmented({ options, value, onChange, size = 'md' }) {
  const fs = size === 'sm' ? 13 : 14;
  return (
    <div style={{ display: 'inline-flex', background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 99, padding: 3, gap: 2 }}>
      {options.map(o => {
        const v = o.value ?? o, l = o.label ?? o, active = v === value;
        return (
          <button key={v} onClick={() => onChange(v)}
            style={{
              display: 'inline-flex', alignItems: 'center', gap: 6, border: 'none', cursor: 'pointer',
              padding: size === 'sm' ? '6px 13px' : '8px 16px', borderRadius: 99, fontSize: fs, fontWeight: 600,
              fontFamily: 'var(--font-body)', transition: 'all .16s',
              background: active ? 'var(--surface)' : 'transparent', color: active ? 'var(--ink)' : 'var(--ink-2)',
              boxShadow: active ? 'var(--shadow-sm)' : 'none',
            }}>
            {o.icon && <Icon name={o.icon} size={fs + 1} />}{l}{o.count != null && <span style={{ fontSize: 11.5, color: 'var(--ink-3)', fontWeight: 600 }}>{o.count}</span>}
          </button>
        );
      })}
    </div>
  );
}

/* ---------- misc ---------- */
function Money({ cur, value, unit }) {
  return <span>{cur}{value.toLocaleString('en-GB')}<span style={{ fontWeight: 500, color: 'var(--ink-2)', fontSize: '0.78em' }}>{unit}</span></span>;
}
function EmptyState({ icon, title, body, action }) {
  return (
    <div style={{ textAlign: 'center', padding: '48px 24px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10 }}>
      <div style={{ width: 56, height: 56, borderRadius: '50%', background: 'var(--surface-2)', display: 'grid', placeItems: 'center', color: 'var(--ink-3)' }}>
        <Icon name={icon} size={24} />
      </div>
      <div style={{ fontFamily: 'var(--font-display)', fontSize: 19, fontWeight: 600 }}>{title}</div>
      <div style={{ color: 'var(--ink-2)', fontSize: 14, maxWidth: 320, lineHeight: 1.5 }}>{body}</div>
      {action && <div style={{ marginTop: 6 }}>{action}</div>}
    </div>
  );
}
function Divider({ label }) {
  if (!label) return <div style={{ height: 1, background: 'var(--line)', width: '100%' }} />;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, color: 'var(--ink-3)' }}>
      <div style={{ height: 1, background: 'var(--line)', flex: 1 }} />
      <span style={{ fontSize: 12, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>{label}</span>
      <div style={{ height: 1, background: 'var(--line)', flex: 1 }} />
    </div>
  );
}

/* ---------- toast ---------- */
function Toast({ toast }) {
  if (!toast) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)', zIndex: 200,
      display: 'flex', alignItems: 'center', gap: 11, background: 'var(--ink)', color: 'var(--bg)',
      padding: '13px 20px', borderRadius: 99, boxShadow: 'var(--shadow-lg)', fontSize: 14, fontWeight: 500,
      animation: 'credo-fade-up .25s ease', maxWidth: '90%',
    }}>
      <span style={{ display: 'grid', placeItems: 'center', width: 22, height: 22, borderRadius: '50%', background: 'var(--brand)', color: '#fff' }}>
        <Icon name="check" size={14} stroke={2.6} />
      </span>
      {toast}
    </div>
  );
}

/* ---------- modal / sheet ---------- */
function Modal({ open, onClose, children, width = 520, mobile }) {
  useEffect(() => {
    const onKey = (e) => e.key === 'Escape' && onClose();
    if (open) window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 150, background: 'rgba(12,18,15,.42)', backdropFilter: 'blur(3px)',
      display: 'flex', alignItems: mobile ? 'flex-end' : 'center', justifyContent: 'center',
      padding: mobile ? 0 : 24, animation: 'credo-fade .18s ease',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: 'var(--surface)', borderRadius: mobile ? 'var(--r-lg) var(--r-lg) 0 0' : 'var(--r-lg)',
        width: mobile ? '100%' : width, maxWidth: '100%', maxHeight: '92%', overflow: 'auto',
        boxShadow: 'var(--shadow-lg)', animation: mobile ? 'credo-fade-up .25s ease' : 'credo-pop .2s ease',
      }}>
        {children}
      </div>
    </div>
  );
}

Object.assign(window, {
  Logo, Button, StatusPill, Tag, Avatar, PropImage, Card, Field, Input, Textarea,
  Select, Segmented, Money, EmptyState, Divider, Toast, Modal, STATUS_TONE,
});
