/* primitives.jsx — Brewly hand-drawn shared components + decorations
   Exports to window. Colors/shadows/fonts via CSS classes; wobble radius
   and per-element rotation stay inline (token-routing rule). */

const wobbly = {
  sm:   { borderRadius: 'var(--wob-sm)' },
  md:   { borderRadius: 'var(--wob-md)' },
  lg:   { borderRadius: 'var(--wob-lg)' },
  pill: { borderRadius: 'var(--wob-pill)' },
  blob: { borderRadius: 'var(--wob-blob)' },
};
// tilt(n) → rotation that scales with the global --tilt Tweak
const tilt = (deg) => ({ transform: `rotate(calc(var(--tilt) * ${deg}deg))` });

/* ---------- Button ---------- */
function Button({ children, variant = 'default', block, disabled, loading, onClick, style, type = 'button', className = '' }) {
  const v = variant === 'accent' ? 'btn--accent'
          : variant === 'secondary' ? 'btn--secondary'
          : variant === 'ghost' ? 'btn--ghost' : '';
  return (
    <button type={type} onClick={onClick} disabled={disabled || loading}
      className={`btn font-body ${v} ${block ? 'btn--block' : ''} ${className}`}
      style={{ ...wobbly.pill, ...style }}>
      {loading ? <Spinner /> : children}
    </button>
  );
}

/* ---------- hand-drawn spinner (dashed coffee ring) ---------- */
function Spinner({ size = 24, color = 'currentColor' }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
      <svg className="spin" width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
        <circle cx="12" cy="12" r="9" fill="none" stroke={color} strokeWidth="2.6"
          strokeLinecap="round" strokeDasharray="6 7" opacity="0.9" />
      </svg>
      <span>…</span>
    </span>
  );
}

/* ---------- Text input ---------- */
function Input({ value, onChange, placeholder, type = 'text', err, inputMode, maxLength, autoFocus, ariaLabel, id, style, onKeyDown, prefix }) {
  const ref = React.useRef(null);
  React.useEffect(() => { if (autoFocus && ref.current) ref.current.focus(); }, [autoFocus]);
  return (
    <div style={{ display: 'flex', alignItems: 'stretch', gap: 8 }}>
      {prefix}
      <input ref={ref} id={id} aria-label={ariaLabel} value={value}
        onChange={(e) => onChange(e.target.value)} onKeyDown={onKeyDown}
        placeholder={placeholder} type={type} inputMode={inputMode}
        maxLength={maxLength}
        className={`field font-body ${err ? 'field--err' : ''}`}
        style={{ ...wobbly.sm, ...style }} />
    </div>
  );
}

/* ---------- Back button (dashed hand-drawn arrow) ---------- */
function BackButton({ onClick }) {
  return (
    <button onClick={onClick} aria-label="Go back"
      className="font-body"
      style={{
        ...wobbly.sm, ...tilt(-2),
        display: 'inline-flex', alignItems: 'center', gap: 6,
        background: 'transparent', border: '2px dashed var(--ink-muted)',
        color: 'var(--ink)', padding: '8px 12px', minHeight: 44,
        cursor: 'pointer', fontSize: 17, WebkitTapHighlightColor: 'transparent',
      }}>
      <svg width="26" height="16" viewBox="0 0 26 16" fill="none" aria-hidden="true">
        <path d="M9 2C5 4 2 6.5 1.5 8c.5 1.5 3.5 4 7.5 6" stroke="currentColor"
          strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"
          strokeDasharray="0.1 5" />
        <path d="M2 8c8 .3 17-.6 23 .2" stroke="currentColor" strokeWidth="2.2"
          strokeLinecap="round" strokeDasharray="4 4" />
      </svg>
      Back
    </button>
  );
}

/* ---------- Progress: 6 wobbly circles + dashed connector ---------- */
function Progress({ step, total = 6 }) {
  return (
    <div role="group" aria-label={`Step ${step} of ${total}`}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 0, padding: '2px 6px' }}>
        {Array.from({ length: total }).map((_, i) => {
          const n = i + 1;
          const state = n < step ? 'done' : n === step ? 'cur' : 'todo';
          return (
            <React.Fragment key={n}>
              {i > 0 && <span className="prog-line" aria-hidden="true" />}
              <span className={`prog-dot prog-dot--${state}`} style={tilt((i % 2 ? 1 : -1) * 1.5)}>
                {state === 'done'
                  ? <svg width="13" height="13" viewBox="0 0 13 13" aria-hidden="true">
                      <path d="M2 7l3 3 6-7" fill="none" stroke="var(--on-accent)" strokeWidth="2.4"
                        strokeLinecap="round" strokeLinejoin="round" /></svg>
                  : n}
              </span>
            </React.Fragment>
          );
        })}
      </div>
      <div className="font-body" style={{ textAlign: 'center', color: 'var(--ink-muted)', fontSize: 15, marginTop: 6 }}>
        Step {step} of {total}
      </div>
    </div>
  );
}

/* ---------- Brewly wordmark (cup + steam doodle) ---------- */
function Wordmark({ size = 26 }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
      <CupMark size={size * 1.05} />
      <span className="font-head" style={{ fontWeight: 700, fontSize: size, color: 'var(--ink)', letterSpacing: '.5px' }}>
        Brewly
      </span>
    </span>
  );
}
function CupMark({ size = 28 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" fill="none" aria-hidden="true">
      <path d="M5 6c1.5-2 3-1 4 0M11 5c1.5-2 3-1 4 .3" stroke="var(--accent)" strokeWidth="1.8" strokeLinecap="round" />
      <path d="M4 13h19c0 7-3 13-9.5 13S4 20 4 13Z" fill="var(--postit)" stroke="var(--ink)" strokeWidth="2" strokeLinejoin="round" />
      <path d="M23 15c4-1 5 1 4 3.5S23 21 22.5 20" stroke="var(--ink)" strokeWidth="2" strokeLinecap="round" fill="none" />
      <path d="M8 17c2 1.6 9 1.6 11 0" stroke="var(--ink)" strokeWidth="1.6" strokeLinecap="round" opacity=".5" />
    </svg>
  );
}

/* ---------- Steam wisps (decorative, floaty) ---------- */
function Steam({ width = 60, color = 'var(--ink-muted)' }) {
  return (
    <svg className="floaty" width={width} height={width * 0.55} viewBox="0 0 60 33" fill="none" aria-hidden="true"
      style={{ '--fr': '0deg' }}>
      <path d="M14 31c-4-6 4-8 0-14s3-9 1-15" stroke={color} strokeWidth="2.4" strokeLinecap="round" />
      <path d="M30 31c-4-6 4-9 0-15s3-8 1-14" stroke={color} strokeWidth="2.4" strokeLinecap="round" />
      <path d="M46 31c-4-6 4-8 0-14s3-9 1-15" stroke={color} strokeWidth="2.4" strokeLinecap="round" />
    </svg>
  );
}

/* ---------- Tack (thumbtack pin) ---------- */
function Tack({ size = 22, style }) {
  return (
    <span aria-hidden="true" style={{
      width: size, height: size, display: 'inline-flex',
      borderRadius: '58% 42% 50% 50% / 50% 55% 45% 50%',
      background: 'var(--accent)', border: '2px solid var(--ink)',
      boxShadow: 'inset -2px -2px 0 rgba(0,0,0,.12)', ...style,
    }} />
  );
}

/* ---------- Tape strip ---------- */
function Tape({ label = '', rotate = -3, style }) {
  return (
    <span className="font-body" style={{
      display: 'inline-block', padding: '3px 16px',
      background: 'var(--tape)', border: '1.5px dashed var(--ink-muted)',
      borderRadius: '4px 8px 5px 7px', color: 'var(--ink-muted)', fontSize: 14,
      ...tilt(rotate), ...style,
    }}>{label}</span>
  );
}

/* ---------- Scribbled check (success) ---------- */
function ScribbleCheck({ size = 132 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 120 120" fill="none" aria-hidden="true">
      <circle className="check-ping" cx="59" cy="60" r="40" fill="none" stroke="var(--accent)" strokeWidth="4" />
      <path className="check-ring" d="M60 8c30-4 54 20 52 48-2 30-28 52-56 50C28 104 6 78 8 50 10 28 30 12 60 8Z"
        fill="none" stroke="var(--ink)" strokeWidth="3" strokeLinecap="round"
        strokeDasharray="3 9" opacity=".55" />
      <path className="draw-check" d="M34 60l18 20 38-44" fill="none" stroke="var(--accent)"
        strokeWidth="9" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ---------- Wavy divider ---------- */
function WavyDivider({ style }) {
  return (
    <svg width="100%" height="10" viewBox="0 0 200 10" preserveAspectRatio="none" aria-hidden="true" style={style}>
      <path d="M0 5c10-6 20 6 30 0s20-6 30 0 20 6 30 0 20-6 30 0 20 6 30 0 20-6 20-2"
        fill="none" stroke="var(--ink-muted)" strokeWidth="2" strokeLinecap="round" />
    </svg>
  );
}

/* ---------- Verified / badge pill ---------- */
function Badge({ children, tone = 'ink' }) {
  const c = tone === 'accent' ? 'var(--accent)' : tone === 'secondary' ? 'var(--secondary)' : 'var(--ink)';
  return (
    <span className="font-body" style={{
      ...wobbly.sm, display: 'inline-flex', alignItems: 'center', gap: 5,
      border: `2px solid ${c}`, color: c, padding: '2px 10px', fontSize: 13.5,
      background: 'var(--surface)', lineHeight: 1.4, whiteSpace: 'nowrap',
    }}>{children}</span>
  );
}

/* ---------- Camera doodle (photo step) ---------- */
function CameraDoodle({ size = 56 }) {
  return (
    <svg width={size} height={size * 0.82} viewBox="0 0 60 48" fill="none" aria-hidden="true">
      <path d="M4 14h11l4-6h22l4 6h11c1 0 2 1 2 2v26c0 1-1 2-2 2H4c-1 0-2-1-2-2V16c0-1 1-2 2-2Z"
        fill="var(--postit)" stroke="var(--ink)" strokeWidth="2.4" strokeLinejoin="round" />
      <circle cx="30" cy="29" r="11" fill="var(--surface)" stroke="var(--ink)" strokeWidth="2.4" />
      <circle cx="30" cy="29" r="4.6" fill="var(--accent)" stroke="var(--ink)" strokeWidth="1.6" />
      <circle cx="50" cy="19" r="1.7" fill="var(--ink)" />
      <path d="M41 5c2-3 5-2 6 .4" stroke="var(--accent)" strokeWidth="2" strokeLinecap="round" />
    </svg>
  );
}

/* ---------- Preset avatars ---------- */
const AVATARS = ['assets/avatars/av1.png', 'assets/avatars/av2.png', 'assets/avatars/av3.png', 'assets/avatars/av4.png', 'assets/avatars/av5.png', 'assets/avatars/av6.png'];

function AvatarRow({ value, onPick, size = 62 }) {
  return (
    <div style={{ display: 'flex', gap: 11, justifyContent: 'center', flexWrap: 'wrap' }}>
      {AVATARS.map((src, i) => {
        const on = value === src;
        return (
          <button key={src} type="button" onClick={() => onPick(src)} aria-label={`Avatar ${i + 1}`} aria-pressed={on}
            style={{
              padding: 0, width: size, height: size, borderRadius: 'var(--wob-blob)',
              transform: `rotate(calc(var(--tilt) * ${(i % 2 ? 1 : -1) * 2}deg)) scale(${on ? 1.06 : 1})`,
              border: on ? '3px solid var(--accent)' : '2px solid var(--ink)',
              boxShadow: on ? 'var(--sh-hard)' : 'var(--sh-soft)', overflow: 'hidden',
              cursor: 'pointer', background: 'var(--surface)', transition: 'transform .12s, box-shadow .12s, border-color .12s',
              WebkitTapHighlightColor: 'transparent',
            }}>
            <img src={src} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          </button>
        );
      })}
    </div>
  );
}

/* ---------- Empty state (shared) ---------- */
function EmptyState({ emoji = '☕', title, body, action, onAction, doodle, fill }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: '32px 26px', minHeight: fill ? '100%' : 260, boxSizing: 'border-box', gap: 4 }}>
      <div className="card" style={{ ...wobbly.lg, ...tilt(-3), width: 104, height: 104, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: 'var(--sh-hard)', marginBottom: 6 }}>
        {doodle || <span style={{ fontSize: 50, lineHeight: 1 }}>{emoji}</span>}
      </div>
      <h3 className="font-head" style={{ fontWeight: 700, fontSize: 26, margin: '12px 0 0', lineHeight: 1.1, maxWidth: 300, textWrap: 'balance' }}>{title}</h3>
      {body && <p className="font-body" style={{ fontSize: 18, lineHeight: 1.4, color: 'var(--ink-muted)', margin: '8px 0 0', maxWidth: 300 }}>{body}</p>}
      {action && <Button variant="accent" onClick={onAction} style={{ marginTop: 18 }}>{action}</Button>}
    </div>
  );
}

Object.assign(window, {
  wobbly, tilt, Button, Spinner, Input, BackButton, Progress,
  Wordmark, CupMark, Steam, Tack, Tape, ScribbleCheck, WavyDivider, Badge, CameraDoodle,
  AVATARS, AvatarRow, EmptyState,
});
