/* UI primitives — icons, chips, buttons, glass surfaces */

/* ─── Ticket-time bucketing ─────────────────────────────────────────
   Operational ticket-time signals carry a 5-minute TTL in the OSS spec.
   Single-minute display would imply kitchen accuracy the data doesn't
   carry. Quantize to 5-minute buckets at every consumer surface — the
   only exception is the post-order status countdown (running progression
   of a known target, not a prediction). Sub-3-minute reads as "almost
   ready" since the bucket boundary doesn't make sense that close in. */
function bucketTicketCompact(m) {
  if (m == null) return null;
  if (m < 3) return '<5m';
  return `~${Math.round(m / 5) * 5}m`;
}
function bucketTicketLong(m) {
  if (m == null) return null;
  if (m < 3) return 'Almost ready';
  return `~${Math.round(m / 5) * 5} min`;
}

/* ─── Icons ─── */
const Ic = {
  Search: ({ s = 16, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="11" cy="11" r="7" stroke={c} strokeWidth="1.8"/>
      <path d="M16 16l5 5" stroke={c} strokeWidth="1.8" strokeLinecap="round"/>
    </svg>
  ),
  Sliders: ({ s = 16, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M4 7h10M18 7h2M4 17h2M10 17h10" stroke={c} strokeWidth="1.8" strokeLinecap="round"/>
      <circle cx="16" cy="7" r="2" fill={c}/>
      <circle cx="8" cy="17" r="2" fill={c}/>
    </svg>
  ),
  Locate: ({ s = 18, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="12" cy="12" r="3.5" fill={c}/>
      <circle cx="12" cy="12" r="8" stroke={c} strokeWidth="1.6"/>
      <path d="M12 1.5v3M12 19.5v3M1.5 12h3M19.5 12h3" stroke={c} strokeWidth="1.6" strokeLinecap="round"/>
    </svg>
  ),
  Layers: ({ s = 18, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M12 3l9 5-9 5-9-5 9-5z" stroke={c} strokeWidth="1.6" strokeLinejoin="round" fill="none"/>
      <path d="M3 13l9 5 9-5" stroke={c} strokeWidth="1.6" strokeLinejoin="round"/>
    </svg>
  ),
  Chevron: ({ s = 16, c = 'currentColor', r = 0 }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none" style={{ transform: `rotate(${r}deg)` }}>
      <path d="M9 6l6 6-6 6" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  ),
  ChevronDown: ({ s = 16, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M6 9l6 6 6-6" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  ),
  X: ({ s = 16, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M6 6l12 12M18 6l-12 12" stroke={c} strokeWidth="2" strokeLinecap="round"/>
    </svg>
  ),
  Clock: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="12" cy="12" r="9" stroke={c} strokeWidth="1.7"/>
      <path d="M12 7v5l3 2" stroke={c} strokeWidth="1.7" strokeLinecap="round"/>
    </svg>
  ),
  Walk: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="13" cy="4.5" r="2" fill={c}/>
      <path d="M11 8.5l-3 5 3 1.5L9 22M14 22l1-7-3-2.5 2-3.5 4 3" stroke={c} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  ),
  Users: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="9" cy="8" r="3.2" stroke={c} strokeWidth="1.7"/>
      <path d="M3 20c.5-3 3-5 6-5s5.5 2 6 5" stroke={c} strokeWidth="1.7" strokeLinecap="round"/>
      <circle cx="17" cy="9" r="2.4" stroke={c} strokeWidth="1.6"/>
      <path d="M14.5 14.5c1-.4 2-.6 3-.6 2 0 4 1.3 4.5 3.5" stroke={c} strokeWidth="1.6" strokeLinecap="round"/>
    </svg>
  ),
  Check: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M5 12.5l5 5L20 7" stroke={c} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  ),
  Plus: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M12 5v14M5 12h14" stroke={c} strokeWidth="2" strokeLinecap="round"/>
    </svg>
  ),
  Heart: ({ s = 16, c = 'currentColor', filled = false }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill={filled ? c : 'none'}>
      <path d="M12 20.5s-7-4.5-9.5-9.5C.5 6.5 4.5 3 8 5.5c1.5 1 2.5 2 4 4 1.5-2 2.5-3 4-4 3.5-2.5 7.5 1 5.5 5.5C19 16 12 20.5 12 20.5z" stroke={c} strokeWidth="1.7" strokeLinejoin="round"/>
    </svg>
  ),
  Pin: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M12 22s7-7 7-12a7 7 0 10-14 0c0 5 7 12 7 12z" stroke={c} strokeWidth="1.7" strokeLinejoin="round"/>
      <circle cx="12" cy="10" r="2.5" stroke={c} strokeWidth="1.6"/>
    </svg>
  ),
  Aura: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <circle cx="12" cy="12" r="3.5" fill={c}/>
      <circle cx="12" cy="12" r="7"   stroke={c} strokeOpacity="0.7" strokeWidth="1.4"/>
      <circle cx="12" cy="12" r="10"  stroke={c} strokeOpacity="0.4" strokeWidth="1.2"/>
    </svg>
  ),
  Bag: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M5 8h14l-1 12H6L5 8z" stroke={c} strokeWidth="1.7" strokeLinejoin="round"/>
      <path d="M9 8V6a3 3 0 016 0v2" stroke={c} strokeWidth="1.7"/>
    </svg>
  ),
  Bell: ({ s = 14, c = 'currentColor' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M6 16l-1.2 1.5h14.4L18 16V11a6 6 0 10-12 0v5z" stroke={c} strokeWidth="1.7" strokeLinejoin="round"/>
      <path d="M10 20a2 2 0 004 0" stroke={c} strokeWidth="1.7" strokeLinecap="round"/>
    </svg>
  ),
  Verified: ({ s = 14, c = '#D9531E' }) => (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
      <path d="M12 2l2 1.5 2.5-.4 1 2.3 2.2 1.4-.5 2.5L21 11l-1.7 2 .5 2.5-2.2 1.4-1 2.3L14 19l-2 1.5L10 19l-2.5.4-1-2.3-2.2-1.4.5-2.5L3 11l1.7-2-.5-2.5L6.4 5.1 7.4 2.8 10 3.5 12 2z" fill={c}/>
      <path d="M8 12.2l2.6 2.6L16 9.4" stroke="#fff" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  ),
};

/* ─── Glass surface (iOS-like) ─── */
function Glass({ children, dark, style, padding = '0' }) {
  return (
    <div style={{
      position: 'relative',
      borderRadius: 999,
      backdropFilter: 'blur(18px) saturate(180%)',
      WebkitBackdropFilter: 'blur(18px) saturate(180%)',
      background: dark ? 'rgba(28,22,18,0.62)' : 'rgba(255,253,248,0.78)',
      border: dark ? '0.5px solid rgba(255,255,255,0.10)' : '0.5px solid rgba(31,27,22,0.06)',
      boxShadow: dark
        ? '0 6px 18px rgba(0,0,0,0.42), 0 1px 0 rgba(255,255,255,0.05) inset'
        : '0 1px 2px rgba(31,27,22,0.06), 0 8px 24px rgba(31,27,22,0.10)',
      padding,
      ...style,
    }}>{children}</div>
  );
}

/* ─── Filter chip ─── */
function FilterChip({ label, active, onClick, leading, dark }) {
  return (
    <button
      onClick={onClick}
      style={{
        display: 'inline-flex', alignItems: 'center', gap: 6,
        height: 34, padding: '0 14px',
        borderRadius: 999, border: 'none', cursor: 'pointer',
        background: active
          ? 'var(--ink)'
          : (dark ? 'rgba(34,28,22,0.86)' : 'rgba(255,253,248,0.92)'),
        color: active ? 'var(--cream)' : 'var(--ink)',
        fontFamily: 'var(--font-body)',
        fontSize: 13.5, fontWeight: 500, letterSpacing: '-0.005em',
        whiteSpace: 'nowrap',
        boxShadow: active
          ? '0 4px 14px rgba(31,27,22,0.18)'
          : (dark ? '0 0 0 0.5px rgba(255,255,255,0.08), 0 1px 2px rgba(0,0,0,0.3)' : '0 0 0 0.5px rgba(31,27,22,0.06), 0 1px 2px rgba(31,27,22,0.04)'),
        transition: 'background 160ms ease, color 160ms ease, transform 160ms ease',
      }}
    >
      {leading}
      {label}
    </button>
  );
}

/* ─── Operational chip ─── */
function OpChip({ icon, label, value, tone = 'default', stale = false, dark }) {
  const palette = {
    default: { bg: dark ? 'rgba(255,255,255,0.06)' : 'rgba(31,27,22,0.05)',  fg: 'var(--ink)' },
    accent:  { bg: dark ? 'rgba(217,83,30,0.18)'   : 'rgba(217,83,30,0.10)',  fg: 'var(--accent)' },
    good:    { bg: dark ? 'rgba(63,174,106,0.18)'  : 'rgba(63,174,106,0.10)', fg: '#3FAE6A' },
    warn:    { bg: dark ? 'rgba(232,176,76,0.20)'  : 'rgba(232,176,76,0.18)', fg: '#A2761B' },
    muted:   { bg: dark ? 'rgba(255,255,255,0.04)' : 'rgba(31,27,22,0.04)',   fg: 'var(--ink-3)' },
  };
  const p = palette[tone];
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      height: 28, padding: '0 10px',
      borderRadius: 999,
      background: p.bg, color: p.fg,
      fontFamily: 'var(--font-body)',
      fontSize: 12.5, fontWeight: 500,
      opacity: stale ? 0.55 : 1,
    }}>
      {icon && <span style={{ display: 'inline-flex', opacity: 0.85 }}>{icon}</span>}
      {label && <span>{label}</span>}
      {value && <span className="mono" style={{ fontWeight: 500 }}>{value}</span>}
    </div>
  );
}

/* ─── Vendor row (compact list item) ─── */
function VendorRow({ v, onClick, preset = 'rings', reducedMotion, intensity, dark }) {
  return (
    <button
      onClick={onClick}
      style={{
        display: 'flex', alignItems: 'center', gap: 14,
        width: '100%', padding: '12px 16px',
        background: 'transparent', border: 'none', cursor: 'pointer',
        textAlign: 'left',
        borderTop: dark ? '0.5px solid rgba(255,255,255,0.07)' : '0.5px solid rgba(31,27,22,0.06)',
        color: 'var(--ink)',
      }}
    >
      {/* Solid color block thumb (tonal) */}
      <div style={{
        width: 56, height: 56, borderRadius: 14,
        background: v.blockTone,
        flexShrink: 0,
        position: 'relative', overflow: 'hidden',
        boxShadow: 'inset 0 0 0 0.5px rgba(0,0,0,0.18)',
      }}>
        <div style={{
          position: 'absolute', inset: 0,
          background: 'radial-gradient(circle at 30% 25%, rgba(255,255,255,0.20), transparent 60%)',
        }}/>
        <div style={{
          position: 'absolute', bottom: 6, left: 8,
          fontFamily: 'var(--font-display)',
          fontSize: 13, color: 'rgba(255,255,255,0.92)',
          fontStyle: 'italic',
          letterSpacing: '-0.01em',
          lineHeight: 1,
        }}>{v.name.split(' ').map(w => w[0]).join('').slice(0,2)}</div>
      </div>

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          display: 'flex', alignItems: 'baseline', gap: 8,
        }}>
          <span style={{ fontFamily: 'var(--font-display)', fontSize: 19, lineHeight: 1.1, color: 'var(--ink)' }}>{v.name}</span>
          {v.tier === 4 && <Ic.Verified s={11} />}
        </div>
        <div style={{
          fontSize: 12.5, color: 'var(--ink-3)',
          marginTop: 3,
          display: 'flex', gap: 6, alignItems: 'center',
        }}>
          <span>{v.cuisine}</span>
          <span style={{ opacity: 0.5 }}>·</span>
          <span>{v.priceTier}</span>
          <span style={{ opacity: 0.5 }}>·</span>
          <span className="mono" style={{ fontSize: 11.5 }}>{v.distance.toFixed(1)} mi</span>
        </div>
        <div style={{ display: 'flex', gap: 6, marginTop: 6 }}>
          {v.accepting && !v.paused && v.tier > 0 && <OpChip tone="good" label="Accepting" icon={<Ic.Check s={10}/>} />}
          {v.paused && <OpChip tone="warn" label="Paused" />}
          {v.accepting && v.ticket > 0 && <OpChip tone="default" icon={<Ic.Clock s={10}/>} value={bucketTicketCompact(v.ticket)} />}
          {v.tier === 0 && <OpChip tone="muted" label="New · unscored" />}
          {v.onSite === 'delayed' && <OpChip tone="warn" label="Delayed" />}
        </div>
      </div>

      <div style={{ flexShrink: 0, position: 'relative' }}>
        <Halo
          tier={v.tier}
          size={48}
          preset={preset}
          reducedMotion={reducedMotion}
          intensity={intensity}
          accepting={v.accepting && !v.paused}
          stale={v.stale}
        />
      </div>
    </button>
  );
}

window.Ic = Ic;
window.Glass = Glass;
window.FilterChip = FilterChip;
window.OpChip = OpChip;
window.VendorRow = VendorRow;
