import { useState, useEffect, useCallback, useRef } from 'react'
import useWaiterFavoritesStore from '../store/waiterFavoritesStore'
import client from '../api/client'

// ── Helpers ──────────────────────────────────────────────────────────────────

function fmt(n) {
  if (n === 0) return ''
  const s = n > 0 ? `+${n.toFixed(2)} €` : `${n.toFixed(2)} €`
  return s
}

function buildInitialState(product) {
  const preferenceSets = product.preference_sets || []

  const prefs = {}
  const subChoices = {}
  const sharedSubs = {}

  preferenceSets.forEach(ps => {
    const def = ps.default_choice_id != null
      ? ps.choices.find(c => c.id === ps.default_choice_id) ?? null
      : null
    prefs[ps.id] = def
    if (def) {
      if (def.sub_choices?.length > 0) {
        subChoices[def.id] = def.sub_choices.find(s => s.is_default) ?? def.sub_choices[0]
      }
      if (ps.shared_subset?.choices?.length > 0 && !def.disables_subset) {
        sharedSubs[ps.id] = ps.shared_subset.choices.find(s => s.is_default) ?? ps.shared_subset.choices[0]
      }
    }
  })

  return { prefs, subChoices, sharedSubs }
}

// Build sorted favorites list across all item types.
// waiterOverride shape: { quick: id[], ingredients: id[], options: id[], prefs: id[] }
// If provided, it fully replaces manager's is_favorite flags.
// Order within each section follows the waiter's id array order.
function buildFavorites(product, waiterOverride) {
  const items = []

  if (waiterOverride) {
    const qi = waiterOverride.quick        || []
    const ii = waiterOverride.ingredients  || []
    const oi = waiterOverride.options      || []
    const pi = waiterOverride.prefs        || []

    qi.forEach((id, idx) => {
      const q = (product.quick_options || []).find(x => x.id === id)
      if (q) items.push({ type: 'quick',      item: q, sortOrder: idx })
    })
    ii.forEach((id, idx) => {
      const ing = (product.ingredients || []).find(x => x.id === id)
      if (ing) items.push({ type: 'ingredient', item: ing, sortOrder: 1000 + idx })
    })
    oi.forEach((id, idx) => {
      const opt = (product.options || []).find(x => x.id === id)
      if (opt) items.push({ type: 'option',     item: opt, sortOrder: 2000 + idx })
    })
    pi.forEach((id, idx) => {
      const ps = (product.preference_sets || []).find(x => x.id === id)
      if (ps) items.push({ type: 'pref',        item: ps,  sortOrder: 3000 + idx })
    })
  } else {
    // Fall back to manager's is_favorite flags
    ;(product.quick_options || []).forEach(q => {
      if (q.is_favorite) items.push({ type: 'quick', item: q, sortOrder: q.favorite_sort_order ?? 0 })
    })
    ;(product.ingredients || []).forEach(ing => {
      if (ing.is_favorite) items.push({ type: 'ingredient', item: ing, sortOrder: ing.favorite_sort_order ?? 0 })
    })
    ;(product.options || []).forEach(opt => {
      if (opt.is_favorite) items.push({ type: 'option', item: opt, sortOrder: opt.favorite_sort_order ?? 0 })
    })
    ;(product.preference_sets || []).forEach(ps => {
      if (ps.is_favorite) items.push({ type: 'pref', item: ps, sortOrder: ps.favorite_sort_order ?? 0 })
    })
  }

  return items.sort((a, b) => a.sortOrder - b.sortOrder)
}

const QUICK_NOTES = ['Χωρίς αλάτι', 'Βγάλτε γρήγορα', 'Αλλεργία!', 'Κόψτε σε μικρά κομμάτια', 'Έξτρα χαρτοπετσέτες']

// ── Primitives ────────────────────────────────────────────────────────────────

function Stepper({ value, onChange, min = 0, max = 99 }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center',
      height: 40, borderRadius: 20,
      background: 'var(--bg2)', border: '1px solid var(--border)',
      overflow: 'hidden',
    }} onClick={e => e.stopPropagation()}>
      <button onClick={() => onChange(Math.max(min, value - 1))} disabled={value <= min}
        style={{ width: 40, height: 40, border: 'none', background: 'transparent', fontSize: 18, fontWeight: 500, cursor: value <= min ? 'default' : 'pointer', color: value <= min ? 'var(--muted)' : 'var(--text)' }}>−</button>
      <div style={{ minWidth: 28, textAlign: 'center', fontSize: 15, fontWeight: 700, color: 'var(--text)', fontVariantNumeric: 'tabular-nums' }}>{value}</div>
      <button onClick={() => onChange(Math.min(max, value + 1))} disabled={value >= max}
        style={{ width: 40, height: 40, border: 'none', background: 'transparent', fontSize: 18, fontWeight: 500, cursor: value >= max ? 'default' : 'pointer', color: value >= max ? 'var(--muted)' : 'var(--text)' }}>+</button>
    </div>
  )
}

function CheckCircle({ selected }) {
  return (
    <div style={{
      width: 24, height: 24, borderRadius: '50%', flexShrink: 0,
      border: `2px solid ${selected ? '#f59e0b' : 'var(--border)'}`,
      background: selected ? '#f59e0b' : 'transparent',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'all 120ms ease',
    }}>
      {selected && <svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M5 12.5L10 17.5L19 7.5" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/></svg>}
    </div>
  )
}

function RadioDot({ selected }) {
  return (
    <div style={{
      width: 22, height: 22, borderRadius: '50%', flexShrink: 0,
      border: `2px solid ${selected ? '#f59e0b' : 'var(--border)'}`,
      background: 'transparent',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'all 120ms ease',
    }}>
      {selected && <div style={{ width: 10, height: 10, borderRadius: '50%', background: '#f59e0b' }} />}
    </div>
  )
}

function Row({ selected, onClick, children, right, left, style = {} }) {
  return (
    <div onClick={onClick} style={{
      padding: '12px 14px',
      background: selected ? 'rgba(245,158,11,0.12)' : 'var(--bg2)',
      border: `1px solid ${selected ? 'rgba(245,158,11,0.4)' : 'var(--border)'}`,
      borderRadius: 12,
      display: 'flex', alignItems: 'center', gap: 12,
      cursor: onClick ? 'pointer' : 'default',
      transition: 'background 120ms ease, border-color 120ms ease',
      minHeight: 56,
      ...style,
    }}>
      {left && <div style={{ flexShrink: 0 }}>{left}</div>}
      <div style={{ flex: 1, minWidth: 0 }}>{children}</div>
      {right && <div style={{ flexShrink: 0 }}>{right}</div>}
    </div>
  )
}

// ── Shared: single quick option row ──────────────────────────────────────────

function QuickOptionRow({ opt, quickState, setQuickState, compact }) {
  const qty = quickState[opt.id] || 0
  const selected = qty > 0
  const toggleSingle = () => setQuickState(s => ({ ...s, [opt.id]: selected ? 0 : 1 }))
  return (
    <Row
      selected={selected}
      onClick={toggleSingle}
      left={<CheckCircle selected={selected} />}
      right={opt.allow_multiple ? (
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }} onClick={e => e.stopPropagation()}>
          {selected
            ? <Stepper value={qty} onChange={v => setQuickState(s => ({ ...s, [opt.id]: v }))} />
            : <button
                onClick={e => { e.stopPropagation(); setQuickState(s => ({ ...s, [opt.id]: 1 })) }}
                style={{ width: 34, height: 34, borderRadius: '50%', background: 'var(--bg3)', border: '1px solid var(--border)', color: 'var(--text)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"/></svg>
              </button>
          }
        </div>
      ) : null}
    >
      <div style={{ fontSize: compact ? 13 : 15, fontWeight: 500, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{opt.name}</div>
      {opt.price > 0 && <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>+{opt.price.toFixed(2)} €{opt.allow_multiple ? ' each' : ''}</div>}
    </Row>
  )
}

// ── Shared: single extra/option row ──────────────────────────────────────────

function ExtraOptionRow({ opt, extrasState, setExtrasState, expandedExtra, setExpandedExtra, compact }) {
  const sel = extrasState[opt.id]
  const selected = !!sel
  const open = expandedExtra === opt.id
  const hasSubs = opt.sub_choices?.length > 0
  const isMultiSelect = opt.multi_select && hasSubs

  // Build sub label for non-multi-select mode
  const subLabel = (!isMultiSelect && sel)
    ? opt.sub_choices?.find(s => s.name === sel.subName)?.name ?? null
    : null
  // For multi-select: subs is { [subName]: qty }
  const subs = sel?.subs ?? {}
  const selectedSubCount = Object.values(subs).filter(q => q > 0).length

  const toggle = () => {
    if (selected) {
      setExtrasState(s => { const n = { ...s }; delete n[opt.id]; return n })
      if (open) setExpandedExtra(null)
    } else {
      if (isMultiSelect) {
        setExtrasState(s => ({ ...s, [opt.id]: { qty: 1, subName: null, subs: {} } }))
        setExpandedExtra(opt.id)
      } else {
        const firstSub = hasSubs ? opt.sub_choices[0] : null
        setExtrasState(s => ({ ...s, [opt.id]: { qty: 1, subName: firstSub?.name ?? null, subs: {} } }))
        if (hasSubs) setExpandedExtra(opt.id)
      }
    }
  }

  return (
    <div>
      <Row
        selected={selected}
        onClick={toggle}
        left={<CheckCircle selected={selected} />}
        right={
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }} onClick={e => e.stopPropagation()}>
            {opt.allow_multiple && !selected && (
              <button
                onClick={e => { e.stopPropagation(); toggle() }}
                style={{ width: 34, height: 34, borderRadius: '50%', background: 'var(--bg3)', border: '1px solid var(--border)', color: 'var(--text)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"/></svg>
              </button>
            )}
            {selected && opt.allow_multiple && !isMultiSelect && (
              <Stepper value={sel.qty} onChange={v => {
                if (v === 0) { setExtrasState(s => { const n = { ...s }; delete n[opt.id]; return n }); return }
                setExtrasState(s => ({ ...s, [opt.id]: { ...sel, qty: v } }))
              }} />
            )}
            {selected && hasSubs && (
              <button onClick={e => { e.stopPropagation(); setExpandedExtra(open ? null : opt.id) }}
                style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--bg3)', border: '1px solid var(--border)', color: 'var(--text)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" style={{ transform: `rotate(${open ? 180 : 0}deg)`, transition: 'transform 180ms' }}>
                  <path d="M6 9L12 15L18 9" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"/>
                </svg>
              </button>
            )}
          </div>
        }
        style={compact ? { minHeight: 48 } : {}}
      >
        <div style={{ fontSize: compact ? 13 : 15, fontWeight: 500, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{opt.name}</div>
        <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>
          {(opt.extra_cost ?? 0) !== 0 ? `+${opt.extra_cost.toFixed(2)} €` : 'Included'}
          {subLabel && <span style={{ color: '#f59e0b', fontWeight: 600 }}> · {subLabel}</span>}
          {isMultiSelect && selectedSubCount > 0 && (
            <span style={{ color: '#f59e0b', fontWeight: 600 }}> · {selectedSubCount} επιλεγμένα</span>
          )}
        </div>
      </Row>

      {/* Single-select sub-choices (radio) */}
      {selected && open && hasSubs && !isMultiSelect && (
        <div style={{ margin: '6px 0 2px 16px', paddingLeft: 14, borderLeft: '2px solid rgba(245,158,11,0.3)', display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          <div style={{ width: '100%', fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '6px 2px 2px' }}>Επιλογή</div>
          {opt.sub_choices.map((sub, si) => {
            const isSel = sel.subName === sub.name
            return (
              <div key={si} style={{ width: sub.is_compact ? 'calc(50% - 3px)' : '100%', minWidth: 0 }}>
                <Row selected={isSel}
                  onClick={() => setExtrasState(s => ({ ...s, [opt.id]: { ...sel, subName: sub.name } }))}
                  left={<RadioDot selected={isSel} />}
                  style={sub.is_compact ? { minHeight: 44 } : {}}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                    <div style={{ fontSize: sub.is_compact ? 12 : 14, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{sub.name}</div>
                    {(sub.extra_cost ?? 0) !== 0 && <div style={{ fontSize: 12, color: 'var(--muted)', flexShrink: 0, marginLeft: 6 }}>+{sub.extra_cost.toFixed(2)} €</div>}
                  </div>
                </Row>
              </div>
            )
          })}
        </div>
      )}

      {/* Multi-select sub-choices (checkboxes, optional qty stepper per sub) */}
      {selected && open && hasSubs && isMultiSelect && (
        <div style={{ margin: '6px 0 2px 16px', paddingLeft: 14, borderLeft: '2px solid rgba(245,158,11,0.3)', display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          <div style={{ width: '100%', fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '6px 2px 2px' }}>Επιλογή (πολλαπλή)</div>
          {opt.sub_choices.map((sub, si) => {
            const subQty = subs[sub.name] || 0
            const subSel = subQty > 0
            const toggleSub = () => {
              const newSubs = { ...subs, [sub.name]: subSel ? 0 : 1 }
              setExtrasState(s => ({ ...s, [opt.id]: { ...sel, subs: newSubs } }))
            }
            return (
              <div key={si} style={{ width: sub.is_compact ? 'calc(50% - 3px)' : '100%', minWidth: 0 }}>
                <Row selected={subSel}
                  onClick={toggleSub}
                  left={<CheckCircle selected={subSel} />}
                  right={sub.allow_multiple && subSel ? (
                    <div onClick={e => e.stopPropagation()}>
                      <Stepper value={subQty} min={1} onChange={v => {
                        const newSubs = { ...subs, [sub.name]: v }
                        setExtrasState(s => ({ ...s, [opt.id]: { ...sel, subs: newSubs } }))
                      }} />
                    </div>
                  ) : null}
                  style={sub.is_compact ? { minHeight: 44 } : {}}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', minWidth: 0 }}>
                    <div style={{ fontSize: sub.is_compact ? 12 : 14, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {sub.name}
                      {subQty > 1 && <span style={{ color: 'var(--muted)', marginLeft: 6, fontSize: 12, fontVariantNumeric: 'tabular-nums' }}>×{subQty}</span>}
                    </div>
                    {(sub.extra_cost ?? 0) !== 0 && <div style={{ fontSize: 12, color: 'var(--muted)', flexShrink: 0, marginLeft: 6 }}>+{sub.extra_cost.toFixed(2)} €{sub.allow_multiple ? ' each' : ''}</div>}
                  </div>
                </Row>
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}

// ── Shared: single ingredient row ─────────────────────────────────────────────

function IngredientRow({ ing, removedState, setRemovedState, compact }) {
  const removed = !!removedState[ing.id]
  return (
    <Row selected={false}
      onClick={() => setRemovedState(s => ({ ...s, [ing.id]: !s[ing.id] }))}
      style={compact ? { minHeight: 48 } : {}}
      right={
        <div style={{
          height: 32, padding: '0 12px', borderRadius: 16,
          background: removed ? 'var(--danger)' : 'var(--bg3)',
          border: `1px solid ${removed ? 'var(--danger)' : 'var(--border)'}`,
          color: removed ? '#fff' : 'var(--text)',
          fontSize: compact ? 11 : 13, fontWeight: 600,
          display: 'inline-flex', alignItems: 'center',
          transition: 'all 120ms ease', whiteSpace: 'nowrap',
        }}>
          {removed ? 'Αφαιρέθηκε' : 'Αφαίρεση'}
        </div>
      }>
      <div style={{ fontSize: compact ? 13 : 15, fontWeight: 500, color: removed ? 'var(--muted)' : 'var(--text)', textDecoration: removed ? 'line-through' : 'none', transition: 'all 120ms', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ing.name}</div>
    </Row>
  )
}

// ── Shared: single preference set ─────────────────────────────────────────────

function PrefSetBlock({ ps, prefs, setPrefs, subChoices, setSubChoices, sharedSubs, setSharedSubs }) {
  const selChoice = prefs[ps.id] ?? null
  const complete = selChoice != null
    && !(selChoice.sub_choices?.length > 0 && subChoices[selChoice.id] == null)
    && !(ps.shared_subset?.choices?.length > 0 && !selChoice.disables_subset && sharedSubs[ps.id] == null)
  const showShared = ps.shared_subset?.choices?.length > 0 && selChoice != null && !selChoice.disables_subset

  function selectPref(choice) {
    setPrefs(p => ({ ...p, [ps.id]: choice }))
    if (choice?.sub_choices?.length > 0) {
      setSubChoices(s => ({ ...s, [choice.id]: s[choice.id] ?? (choice.sub_choices.find(x => x.is_default) ?? choice.sub_choices[0]) }))
    }
    if (ps.shared_subset?.choices?.length > 0 && !choice?.disables_subset) {
      setSharedSubs(s => s[ps.id] != null ? s : { ...s, [ps.id]: ps.shared_subset.choices.find(x => x.is_default) ?? ps.shared_subset.choices[0] })
    }
  }

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, padding: '0 2px 10px' }}>
        <div style={{ fontSize: 14, fontWeight: 700, color: complete ? 'var(--text)' : '#ef4444' }}>{ps.name}</div>
        {!complete && <div style={{ fontSize: 11, fontWeight: 700, color: '#ef4444', textTransform: 'uppercase', letterSpacing: 0.6 }}>Απαιτείται</div>}
      </div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
        {ps.choices.map(ch => {
          const isSel = selChoice?.id === ch.id
          const hasSubs = ch.sub_choices?.length > 0
          const subMissing = isSel && hasSubs && subChoices[ch.id] == null

          return (
            <div key={ch.id} style={{ width: ch.is_compact ? 'calc(50% - 4px)' : '100%', minWidth: 0 }}>
              <Row selected={isSel} onClick={() => selectPref(ch)} left={<RadioDot selected={isSel} />}
                style={ch.is_compact ? { minHeight: 48 } : {}}
                right={(ch.extra_cost ?? 0) !== 0 ? <div style={{ fontSize: ch.is_compact ? 12 : 14, fontWeight: 500, color: 'var(--muted)', flexShrink: 0 }}>{ch.extra_cost > 0 ? '+' : ''}{ch.extra_cost.toFixed(2)} €</div> : null}>
                <div style={{ fontSize: ch.is_compact ? 13 : 15, fontWeight: 500, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ch.name}</div>
              </Row>

              {isSel && hasSubs && (
                <div style={{ margin: '6px 0 2px 16px', paddingLeft: 14, borderLeft: `2px solid ${subMissing ? '#ef4444' : 'rgba(245,158,11,0.3)'}`, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                  {subMissing && <p style={{ width: '100%', fontSize: 12, color: '#ef4444', margin: '4px 2px 2px' }}>— απαιτείται επιλογή</p>}
                  {ch.sub_choices.map((sub, si) => {
                    const subSel = subChoices[ch.id]?.name === sub.name
                    return (
                      <div key={si} style={{ width: sub.is_compact ? 'calc(50% - 3px)' : '100%', minWidth: 0 }}>
                        <Row selected={subSel} onClick={() => setSubChoices(s => ({ ...s, [ch.id]: sub }))} left={<RadioDot selected={subSel} />}
                          style={sub.is_compact ? { minHeight: 44 } : {}}
                          right={(sub.extra_cost ?? 0) !== 0 ? <div style={{ fontSize: 12, color: 'var(--muted)', flexShrink: 0 }}>+{sub.extra_cost.toFixed(2)} €</div> : null}>
                          <div style={{ fontSize: sub.is_compact ? 12 : 14, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{sub.name}</div>
                        </Row>
                      </div>
                    )
                  })}
                </div>
              )}
            </div>
          )
        })}

        {showShared && (
          <div style={{ marginTop: 4, marginLeft: 8, paddingLeft: 14, borderLeft: '2px solid rgba(245,158,11,0.3)', width: '100%' }}>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '4px 2px 6px' }}>{ps.shared_subset.name}</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {ps.shared_subset.choices.map((sub, si) => {
                const subSel = sharedSubs[ps.id]?.name === sub.name
                return (
                  <div key={si} style={{ width: sub.is_compact ? 'calc(50% - 3px)' : '100%', minWidth: 0 }}>
                    <Row selected={subSel} onClick={() => setSharedSubs(s => ({ ...s, [ps.id]: sub }))} left={<RadioDot selected={subSel} />}
                      style={sub.is_compact ? { minHeight: 44 } : {}}
                      right={(sub.extra_cost ?? 0) !== 0 ? <div style={{ fontSize: 12, color: 'var(--muted)', flexShrink: 0 }}>+{sub.extra_cost.toFixed(2)} €</div> : null}>
                      <div style={{ fontSize: sub.is_compact ? 12 : 14, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{sub.name}</div>
                    </Row>
                  </div>
                )
              })}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

// ── Tab: Favorites ────────────────────────────────────────────────────────────

function FavoritesTab({ product, waiterOverride, quickState, setQuickState, extrasState, setExtrasState, expandedExtra, setExpandedExtra, removedState, setRemovedState, prefs, setPrefs, subChoices, setSubChoices, sharedSubs, setSharedSubs }) {
  const favorites = buildFavorites(product, waiterOverride)

  if (favorites.length === 0) return (
    <p style={{ color: 'var(--muted)', textAlign: 'center', padding: '32px 0', fontSize: 14 }}>Δεν υπάρχουν αγαπημένα για αυτό το προϊόν.</p>
  )

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {favorites.map((fav, fi) => {
        if (fav.type === 'quick') {
          return <QuickOptionRow key={`quick-${fav.item.id}`} opt={fav.item} quickState={quickState} setQuickState={setQuickState} compact={false} />
        }
        if (fav.type === 'ingredient') {
          return <IngredientRow key={`ing-${fav.item.id}`} ing={fav.item} removedState={removedState} setRemovedState={setRemovedState} compact={false} />
        }
        if (fav.type === 'option') {
          return <ExtraOptionRow key={`opt-${fav.item.id}`} opt={fav.item} extrasState={extrasState} setExtrasState={setExtrasState} expandedExtra={expandedExtra} setExpandedExtra={setExpandedExtra} compact={false} />
        }
        if (fav.type === 'pref') {
          return (
            <PrefSetBlock key={`pref-${fav.item.id}`} ps={fav.item}
              prefs={prefs} setPrefs={setPrefs}
              subChoices={subChoices} setSubChoices={setSubChoices}
              sharedSubs={sharedSubs} setSharedSubs={setSharedSubs}
            />
          )
        }
        return null
      })}
    </div>
  )
}

// ── Tab: Quick Options ────────────────────────────────────────────────────────

function QuickTab({ product, quickState, setQuickState }) {
  const quickOptions = product.quick_options || []
  if (quickOptions.length === 0) return (
    <p style={{ color: 'var(--muted)', textAlign: 'center', padding: '32px 0', fontSize: 14 }}>Δεν υπάρχουν γρήγορες επιλογές.</p>
  )
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
      {quickOptions.map(opt => (
        <div key={opt.id} style={{ width: opt.is_compact ? 'calc(50% - 4px)' : '100%', minWidth: 0 }}>
          <QuickOptionRow opt={opt} quickState={quickState} setQuickState={setQuickState} compact={opt.is_compact} />
        </div>
      ))}
    </div>
  )
}

// ── Shared: PWA group sticky header ──────────────────────────────────────────

// Static group colours — cycle by index passed from parent
const GROUP_COLORS = [
  { bg: '#e0e7ff', border: '#a5b4fc', text: '#3730a3' }, // indigo
  { bg: '#fce7f3', border: '#f9a8d4', text: '#9d174d' }, // pink
  { bg: '#d1fae5', border: '#6ee7b7', text: '#065f46' }, // emerald
  { bg: '#fef3c7', border: '#fcd34d', text: '#92400e' }, // amber
  { bg: '#e0f2fe', border: '#7dd3fc', text: '#075985' }, // sky
  { bg: '#f3e8ff', border: '#d8b4fe', text: '#581c87' }, // purple
]

function PWAGroupHeader({ name, collapsed, onToggle, colorIdx = 0 }) {
  const c = GROUP_COLORS[colorIdx % GROUP_COLORS.length]
  return (
    <div
      onClick={onToggle}
      style={{
        position: 'sticky', top: 0, zIndex: 10,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '10px 14px',
        background: c.bg,
        border: `1.5px solid ${c.border}`,
        borderRadius: 10,
        cursor: 'pointer',
        userSelect: 'none',
        marginBottom: collapsed ? 0 : 8,
      }}
    >
      <span style={{ fontSize: 14, fontWeight: 700, color: c.text, letterSpacing: '0.02em' }}>{name}</span>
      <span style={{ fontSize: 16, color: c.text, transition: 'transform 0.15s', display: 'inline-block', transform: collapsed ? 'rotate(-90deg)' : 'rotate(0deg)' }}>▾</span>
    </div>
  )
}

// Partition items into { ungrouped, groups: [{group, items}] } preserving order
function partitionByGroup(items, modifierGroups) {
  if (!modifierGroups || modifierGroups.length === 0) return { ungrouped: items, groups: [] }
  const groupMap = {}
  modifierGroups.forEach(g => { groupMap[g.id] = { group: g, items: [] } })
  const ungrouped = []
  items.forEach(item => {
    if (item.group_id != null && groupMap[item.group_id]) {
      groupMap[item.group_id].items.push(item)
    } else {
      ungrouped.push(item)
    }
  })
  // Preserve group order from modifierGroups
  const groups = modifierGroups.map(g => groupMap[g.id]).filter(g => g.items.length > 0)
  return { ungrouped, groups }
}

// ── Tab: Extras ───────────────────────────────────────────────────────────────

function ExtrasTab({ product, extrasState, setExtrasState, expandedExtra, setExpandedExtra }) {
  const extraGroups = (product.modifier_groups || []).filter(g => g.modifier_type === 'option')
  const [collapsedGroups, setCollapsedGroups] = useState(() => Object.fromEntries(extraGroups.map(g => [g.id, true])))
  const options = product.options || []
  if (options.length === 0) return (
    <p style={{ color: 'var(--muted)', textAlign: 'center', padding: '32px 0', fontSize: 14 }}>Δεν υπάρχουν extras.</p>
  )

  function toggleGroup(id) { setCollapsedGroups(s => ({ ...s, [id]: !s[id] })) }

  const { ungrouped, groups } = partitionByGroup(options, extraGroups)

  function renderOption(opt) {
    return (
      <div key={opt.id} style={{ width: opt.is_compact ? 'calc(50% - 4px)' : '100%', minWidth: 0 }}>
        <ExtraOptionRow opt={opt} extrasState={extrasState} setExtrasState={setExtrasState} expandedExtra={expandedExtra} setExpandedExtra={setExpandedExtra} compact={opt.is_compact} />
      </div>
    )
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
      {ungrouped.length > 0 && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: groups.length > 0 ? 12 : 0 }}>
          {ungrouped.map(renderOption)}
        </div>
      )}
      {groups.map(({ group, items }, gi) => {
        const isCollapsed = collapsedGroups[group.id] ?? true
        return (
          <div key={group.id} style={{ marginBottom: 12 }}>
            <PWAGroupHeader name={group.name} collapsed={isCollapsed} onToggle={() => toggleGroup(group.id)} colorIdx={gi} />
            {!isCollapsed && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                {items.map(renderOption)}
              </div>
            )}
          </div>
        )
      })}
    </div>
  )
}

// ── Tab: Υλικά (Ingredients) ─────────────────────────────────────────────────

function IngredientsTab({ product, removedState, setRemovedState }) {
  const ingGroups = (product.modifier_groups || []).filter(g => g.modifier_type === 'ingredient')
  const [collapsedGroups, setCollapsedGroups] = useState(() => Object.fromEntries(ingGroups.map(g => [g.id, true])))
  const ingredients = product.ingredients || []
  if (ingredients.length === 0) return (
    <p style={{ color: 'var(--muted)', textAlign: 'center', padding: '32px 0', fontSize: 14 }}>Δεν υπάρχουν υλικά.</p>
  )

  function toggleGroup(id) { setCollapsedGroups(s => ({ ...s, [id]: !s[id] })) }

  const { ungrouped, groups } = partitionByGroup(ingredients, ingGroups)

  function renderIng(ing) {
    return (
      <div key={ing.id} style={{ width: ing.is_compact ? 'calc(50% - 4px)' : '100%', minWidth: 0 }}>
        <IngredientRow ing={ing} removedState={removedState} setRemovedState={setRemovedState} compact={ing.is_compact} />
      </div>
    )
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
      {ungrouped.length > 0 && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: groups.length > 0 ? 12 : 0 }}>
          {ungrouped.map(renderIng)}
        </div>
      )}
      {groups.map(({ group, items }, gi) => {
        const isCollapsed = collapsedGroups[group.id] ?? true
        return (
          <div key={group.id} style={{ marginBottom: 12 }}>
            <PWAGroupHeader name={group.name} collapsed={isCollapsed} onToggle={() => toggleGroup(group.id)} colorIdx={gi} />
            {!isCollapsed && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                {items.map(renderIng)}
              </div>
            )}
          </div>
        )
      })}
    </div>
  )
}

// ── Tab: Προτιμήσεις ─────────────────────────────────────────────────────────

function PrefsTab({ product, prefs, setPrefs, subChoices, setSubChoices, sharedSubs, setSharedSubs }) {
  const prefGroups = (product.modifier_groups || []).filter(g => g.modifier_type === 'preference')
  const [collapsedGroups, setCollapsedGroups] = useState(() => Object.fromEntries(prefGroups.map(g => [g.id, true])))
  const preferenceSets = product.preference_sets || []
  if (preferenceSets.length === 0) return (
    <p style={{ color: 'var(--muted)', textAlign: 'center', padding: '32px 0', fontSize: 14 }}>Δεν υπάρχουν προτιμήσεις.</p>
  )

  function toggleGroup(id) { setCollapsedGroups(s => ({ ...s, [id]: !s[id] })) }

  const { ungrouped, groups } = partitionByGroup(preferenceSets, prefGroups)

  function renderPrefSet(ps) {
    return (
      <PrefSetBlock key={ps.id} ps={ps}
        prefs={prefs} setPrefs={setPrefs}
        subChoices={subChoices} setSubChoices={setSubChoices}
        sharedSubs={sharedSubs} setSharedSubs={setSharedSubs}
      />
    )
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
      {ungrouped.length > 0 && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 24, marginBottom: groups.length > 0 ? 16 : 0 }}>
          {ungrouped.map(renderPrefSet)}
        </div>
      )}
      {groups.map(({ group, items }, gi) => {
        const isCollapsed = collapsedGroups[group.id] ?? true
        return (
          <div key={group.id} style={{ marginBottom: 16 }}>
            <PWAGroupHeader name={group.name} collapsed={isCollapsed} onToggle={() => toggleGroup(group.id)} colorIdx={gi} />
            {!isCollapsed && (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
                {items.map(renderPrefSet)}
              </div>
            )}
          </div>
        )
      })}
    </div>
  )
}

// ── Tab: Quantity (for KG / Liter / Gram / mL units) ─────────────────────────

const DECIMAL_UNIT_CONFIG = {
  kg:    { step: 0.05, min: 0.05, presets: [0.10, 0.20, 0.25, 0.50, 0.70, 1.00, 1.50, 2.00, 2.50, 3.00, 4.00, 5.00], offsets: [0.1, 0.2, 0.5, 1.0], label: 'kg' },
  liter: { step: 0.05, min: 0.05, presets: [0.10, 0.20, 0.25, 0.50, 0.70, 1.00, 1.50, 2.00, 2.50, 3.00, 4.00, 5.00], offsets: [0.1, 0.2, 0.5, 1.0], label: 'L'  },
  gram:  { step: 10,   min: 10,   presets: [50, 100, 150, 200, 250, 300, 400, 500], offsets: [10, 50, 100, 200], label: 'g'  },
  ml:    { step: 5,    min: 5,    presets: [25, 50, 100, 150, 200, 250, 300, 500], offsets: [25, 50, 100, 200],  label: 'mL' },
}

function fmtDecimalQty(qty, cfg) {
  if (!cfg) return String(qty)
  if (cfg.label === 'kg' || cfg.label === 'L') {
    const n = Number(qty)
    return n % 1 === 0 ? n.toFixed(1) : (Math.round(n * 100) / 100).toFixed(2).replace(/0$/, '')
  }
  return String(qty)
}

function QuantityTab({ unitCfg, qty, setQty }) {
  const [editingQty, setEditingQty] = useState(false)
  const [qtyInput, setQtyInput] = useState('')
  const inputRef = useRef(null)

  function clamp(v) { return Math.max(unitCfg.min, Math.round(v * 1000) / 1000) }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Main − / value / + row */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 0 }}>
        <div style={{ display: 'inline-flex', alignItems: 'center', height: 52, borderRadius: 26, background: 'var(--bg3)', border: '1px solid var(--border)', overflow: 'hidden' }}>
          <button
            onClick={() => setQty(q => clamp(q - unitCfg.step))}
            style={{ width: 52, height: 52, border: 'none', background: 'transparent', fontSize: 22, fontWeight: 500, cursor: 'pointer', color: 'var(--text)' }}
          >−</button>
          {editingQty ? (
            <input
              ref={inputRef}
              type="number"
              inputMode="decimal"
              value={qtyInput}
              onChange={e => setQtyInput(e.target.value)}
              onBlur={() => {
                const v = parseFloat(qtyInput)
                if (!isNaN(v)) setQty(clamp(v))
                setEditingQty(false)
              }}
              onKeyDown={e => { if (e.key === 'Enter') e.target.blur() }}
              autoFocus
              style={{
                width: 80, height: 52, border: 'none', background: 'transparent',
                textAlign: 'center', fontSize: 17, fontWeight: 700, color: 'var(--text)',
                fontVariantNumeric: 'tabular-nums', outline: 'none', fontFamily: 'inherit',
              }}
            />
          ) : (
            <div
              onClick={() => { setQtyInput(String(qty)); setEditingQty(true) }}
              style={{ minWidth: 80, textAlign: 'center', fontSize: 17, fontWeight: 700, color: 'var(--text)', fontVariantNumeric: 'tabular-nums', cursor: 'text', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }}
            >
              {fmtDecimalQty(qty, unitCfg)}
              <span style={{ fontSize: 13, fontWeight: 500, opacity: 0.65 }}>{unitCfg.label}</span>
            </div>
          )}
          <button
            onClick={() => setQty(q => clamp(q + unitCfg.step))}
            style={{ width: 52, height: 52, border: 'none', background: 'transparent', fontSize: 22, fontWeight: 500, cursor: 'pointer', color: 'var(--text)' }}
          >+</button>
        </div>
      </div>

      {/* Quick presets — 3 rows of 4 */}
      <div>
        <p style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', letterSpacing: 0.8, marginBottom: 8, textAlign: 'center' }}>ΓΡΗΓΟΡΗ ΕΠΙΛΟΓΗ</p>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
          {unitCfg.presets.map(v => (
            <button
              key={v}
              onClick={() => setQty(v)}
              style={{
                padding: '10px 4px', borderRadius: 12, border: 'none',
                background: qty === v ? 'var(--accent)' : 'var(--bg3)',
                color: qty === v ? 'var(--accent-fg)' : 'var(--text)',
                fontSize: 13, fontWeight: 700, cursor: 'pointer',
                textAlign: 'center',
              }}
            >
              {fmtDecimalQty(v, unitCfg)}{unitCfg.label}
            </button>
          ))}
        </div>
      </div>

      {/* Quick ± offset buttons — 2×2 grid */}
      <div>
        <p style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', letterSpacing: 0.8, marginBottom: 8, textAlign: 'center' }}>ΓΡΗΓΟΡΗ ΠΡΟΣΘΗΚΗ</p>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8 }}>
          {unitCfg.offsets.map(off => (
            <button
              key={`+${off}`}
              onClick={() => setQty(q => clamp(q + off))}
              style={{
                padding: '10px 4px', borderRadius: 12, border: 'none',
                background: 'rgba(34,197,94,0.12)', color: '#4ade80',
                fontSize: 13, fontWeight: 700, cursor: 'pointer', textAlign: 'center',
              }}
            >+{fmtDecimalQty(off, unitCfg)}{unitCfg.label}</button>
          ))}
          {unitCfg.offsets.map(off => (
            <button
              key={`-${off}`}
              onClick={() => setQty(q => clamp(q - off))}
              style={{
                padding: '10px 4px', borderRadius: 12, border: 'none',
                background: 'rgba(239,68,68,0.12)', color: '#fca5a5',
                fontSize: 13, fontWeight: 700, cursor: 'pointer', textAlign: 'center',
              }}
            >−{fmtDecimalQty(off, unitCfg)}{unitCfg.label}</button>
          ))}
        </div>
      </div>
    </div>
  )
}

// ── Tab: Price Adjustment ─────────────────────────────────────────────────────

const PRICE_DELTAS = [-5, -3, -2, -1, -0.5, -0.2, +0.2, +0.5, +1, +2, +3, +5]

function PriceAdjustTab({ basePrice, priceAdj, setPriceAdj }) {
  const [editing, setEditing] = useState(false)
  const [rawInput, setRawInput] = useState('')
  const inputRef = useRef(null)
  const effectivePrice = basePrice + priceAdj

  function applyDelta(d) {
    setPriceAdj(a => {
      const next = Math.round((a + d) * 100) / 100
      const min = -(basePrice - 0.01)
      return Math.max(min, next)
    })
  }

  function commitInput() {
    const v = parseFloat(rawInput.replace(',', '.'))
    if (!isNaN(v) && v >= 0.01) {
      setPriceAdj(Math.round((v - basePrice) * 100) / 100)
    }
    setEditing(false)
  }

  useEffect(() => {
    if (editing && inputRef.current) inputRef.current.focus()
  }, [editing])

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
      <div style={{ padding: '10px 14px', background: 'rgba(245,158,11,0.08)', border: '1px solid rgba(245,158,11,0.2)', borderRadius: 10, fontSize: 13, color: '#f59e0b' }}>
        Αλλαγή τιμής μόνο για αυτό το αντικείμενο. Δεν επηρεάζει άλλες παραγγελίες.
      </div>

      {/* Price display / input */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
        <button onClick={() => applyDelta(-0.1)} style={{ width: 44, height: 44, borderRadius: '50%', border: '1.5px solid var(--border)', background: 'var(--bg3)', fontSize: 20, fontWeight: 700, color: 'var(--text)', cursor: 'pointer' }}>−</button>
        {editing ? (
          <input
            ref={inputRef}
            type="number"
            inputMode="decimal"
            value={rawInput}
            onChange={e => setRawInput(e.target.value)}
            onBlur={commitInput}
            onKeyDown={e => { if (e.key === 'Enter') e.target.blur() }}
            style={{ width: 110, height: 52, border: '2px solid #f59e0b', borderRadius: 14, background: 'var(--bg2)', textAlign: 'center', fontSize: 22, fontWeight: 800, color: '#f59e0b', outline: 'none', fontFamily: 'inherit' }}
          />
        ) : (
          <button onClick={() => { setRawInput(effectivePrice.toFixed(2)); setEditing(true) }} style={{
            minWidth: 110, height: 52, borderRadius: 14,
            border: `2px solid ${priceAdj !== 0 ? '#f59e0b' : 'var(--border)'}`,
            background: priceAdj !== 0 ? 'rgba(245,158,11,0.12)' : 'var(--bg2)',
            color: priceAdj !== 0 ? '#f59e0b' : 'var(--text)',
            fontSize: 22, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit',
          }}>
            {effectivePrice.toFixed(2)} €
          </button>
        )}
        <button onClick={() => applyDelta(+0.1)} style={{ width: 44, height: 44, borderRadius: '50%', border: '1.5px solid var(--border)', background: 'var(--bg3)', fontSize: 20, fontWeight: 700, color: 'var(--text)', cursor: 'pointer' }}>+</button>
      </div>

      {priceAdj !== 0 && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10 }}>
          <span style={{ fontSize: 13, color: 'var(--muted)' }}>Βάση: {basePrice.toFixed(2)} €</span>
          <span style={{ fontSize: 13, fontWeight: 700, color: priceAdj > 0 ? '#4ade80' : '#f87171' }}>
            {priceAdj > 0 ? '+' : ''}{priceAdj.toFixed(2)} €
          </span>
          <button onClick={() => setPriceAdj(0)} style={{ padding: '3px 10px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg3)', color: 'var(--muted)', fontSize: 12, cursor: 'pointer' }}>Επαναφορά</button>
        </div>
      )}

      {/* Quick delta grid — 4 rows × 3 */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
        {PRICE_DELTAS.map(d => (
          <button
            key={d}
            onClick={() => applyDelta(d)}
            style={{
              padding: '11px 4px', borderRadius: 12, border: 'none',
              background: d < 0 ? 'rgba(239,68,68,0.12)' : 'rgba(34,197,94,0.12)',
              color: d < 0 ? '#fca5a5' : '#4ade80',
              fontSize: 14, fontWeight: 700, cursor: 'pointer',
            }}
          >
            {d > 0 ? '+' : ''}{d.toFixed(2 - (Number.isInteger(d) ? 2 : 0))} €
          </button>
        ))}
      </div>
    </div>
  )
}

// ── Tab: Notes ────────────────────────────────────────────────────────────────

function NotesTab({ note, setNote, quickNotes = FALLBACK_QUICK_NOTES }) {
  return (
    <div>
      <textarea
        value={note}
        onChange={e => setNote(e.target.value)}
        placeholder="π.χ. Χωρίς αλάτι, κόψτε στη μέση..."
        rows={5}
        style={{ width: '100%', padding: 14, fontSize: 15, fontFamily: 'inherit', color: 'var(--text)', background: 'var(--bg2)', border: '1px solid var(--border)', borderRadius: 12, resize: 'none', outline: 'none', boxSizing: 'border-box' }}
      />
      {quickNotes.length > 0 && (
        <>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6, marginTop: 20, marginBottom: 8 }}>Γρήγορες σημειώσεις</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {quickNotes.map(q => (
              <button key={q} onClick={() => setNote(n => n ? `${n}\n${q}` : q)}
                style={{ height: 36, padding: '0 14px', borderRadius: 18, background: 'var(--bg2)', border: '1px solid var(--border)', color: 'var(--text)', fontSize: 13, fontWeight: 500, cursor: 'pointer' }}>
                + {q}
              </button>
            ))}
          </div>
        </>
      )}
    </div>
  )
}

// ── Tab: Summary ──────────────────────────────────────────────────────────────

function SummaryTab({ product, summaryLines, note, onJumpTab }) {
  const isEmpty = summaryLines.length === 0 && !note
  const byGroup = { quick: [], extras: [], removed: [], prefs: [] }
  summaryLines.forEach(l => byGroup[l.group]?.push(l))

  const Section = ({ title, tab, lines }) => lines.length === 0 ? null : (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0 2px 8px' }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6 }}>{title}</div>
        <button onClick={() => onJumpTab(tab)} style={{ background: 'none', border: 'none', fontSize: 12, fontWeight: 700, color: '#f59e0b', cursor: 'pointer', textTransform: 'uppercase', letterSpacing: 0.6 }}>Αλλαγή</button>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        {lines.map((l, i) => (
          <div key={i} style={{ padding: '10px 14px', background: 'var(--bg2)', border: '1px solid var(--border)', borderRadius: 10, display: 'flex', alignItems: 'center', gap: 10, minHeight: 44 }}>
            <div style={{ flex: 1 }}>
              {l.group === 'prefs' ? (
                <>
                  <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 2 }}>{l.label}</div>
                  <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--text)' }}>{l.value}</div>
                </>
              ) : l.group === 'removed' ? (
                <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--text)' }}>
                  Χωρίς {l.label}
                </div>
              ) : l.group === 'extras' ? (
                <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--text)' }}>
                  {l.label}
                  {l.subName && <span> · {l.subName}</span>}
                  {l.qty > 1 && <span style={{ color: 'var(--muted)', marginLeft: 6, fontVariantNumeric: 'tabular-nums' }}>×{l.qty}</span>}
                </div>
              ) : (
                <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--text)' }}>
                  {l.qty > 1 && <span style={{ color: 'var(--muted)', marginRight: 6, fontVariantNumeric: 'tabular-nums' }}>{l.qty}×</span>}
                  {l.label}
                </div>
              )}
            </div>
            {l.price !== 0 && <div style={{ fontSize: 13, fontWeight: 600, color: l.price < 0 ? 'var(--danger)' : 'var(--text)', fontVariantNumeric: 'tabular-nums' }}>{l.price > 0 ? '+' : ''}{l.price.toFixed(2)} €</div>}
          </div>
        ))}
      </div>
    </div>
  )

  return (
    <div>
      {isEmpty ? (
        <div style={{ padding: '40px 16px', textAlign: 'center', color: 'var(--muted)', fontSize: 14 }}>
          Δεν έχει γίνει καμία προσαρμογή. Χρησιμοποιήστε τις καρτέλες για να διαμορφώσετε το προϊόν.
        </div>
      ) : (
        <>
          <Section title="Προτιμήσεις" tab="prefs" lines={byGroup.prefs} />
          <Section title="Γρήγορες Επιλογές" tab="quick" lines={byGroup.quick} />
          <Section title="Extras" tab="extras" lines={byGroup.extras} />
          <Section title="Αφαιρέθηκαν" tab="ingredients" lines={byGroup.removed} />
          {note && (
            <div style={{ marginBottom: 20 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0 2px 8px' }}>
                <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.6 }}>Σημείωση</div>
                <button onClick={() => onJumpTab('notes')} style={{ background: 'none', border: 'none', fontSize: 12, fontWeight: 700, color: '#f59e0b', cursor: 'pointer', textTransform: 'uppercase', letterSpacing: 0.6 }}>Αλλαγή</button>
              </div>
              <div style={{ padding: '12px 14px', background: 'rgba(245,158,11,0.08)', border: '1px solid rgba(245,158,11,0.2)', borderRadius: 10, fontSize: 14, color: 'var(--text)', lineHeight: 1.4, whiteSpace: 'pre-wrap' }}>{note}</div>
            </div>
          )}
        </>
      )}
    </div>
  )
}

// ── Main OrderDrawer ──────────────────────────────────────────────────────────

function CoursesTab({ courses, courseId, setCourseId }) {
  return (
    <div style={{ padding: '12px 16px', display: 'flex', flexDirection: 'column', gap: 8 }}>
      <button
        onClick={() => setCourseId(null)}
        style={{
          padding: '10px 14px', borderRadius: 10, textAlign: 'left',
          background: courseId === null ? 'var(--accent)' : 'var(--card)',
          color: courseId === null ? '#fff' : 'var(--text)',
          border: `2px solid ${courseId === null ? 'var(--accent)' : 'var(--line)'}`,
          fontWeight: 600, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit',
        }}
      >
        No course (fire immediately)
      </button>
      {courses.map(c => (
        <button
          key={c.id}
          onClick={() => setCourseId(courseId === c.id ? null : c.id)}
          style={{
            padding: '10px 14px', borderRadius: 10, textAlign: 'left',
            background: courseId === c.id ? c.color : 'var(--card)',
            color: courseId === c.id ? '#fff' : 'var(--text)',
            border: `2px solid ${courseId === c.id ? c.color : 'var(--line)'}`,
            fontWeight: 600, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit',
            display: 'flex', alignItems: 'center', gap: 10,
          }}
        >
          <span style={{
            width: 12, height: 12, borderRadius: '50%',
            background: courseId === c.id ? 'rgba(255,255,255,0.5)' : c.color,
            flexShrink: 0,
          }} />
          {c.name}
        </button>
      ))}
    </div>
  )
}

const FALLBACK_QUICK_NOTES = ['Χωρίς αλάτι', 'Βγάλτε γρήγορα', 'Αλλεργία!', 'Κόψτε σε μικρά κομμάτια', 'Έξτρα χαρτοπετσέτες']

export default function OrderDrawer({ product, isOpen, onClose, onAdd, initialState, courses, quickNotes }) {
  const itemFavorites = useWaiterFavoritesStore(s => s.itemFavorites)
  const [priceAdjAllowed, setPriceAdjAllowed] = useState(false)

  useEffect(() => {
    client.get('/api/settings/')
      .then(r => setPriceAdjAllowed(r.data?.['orders.waiter_price_adjust_allowed']?.value === 'true'))
      .catch(() => {})
  }, [])

  const preferenceSets = product?.preference_sets || []
  const quickOptions = product?.quick_options || []
  const options = product?.options || []
  const ingredients = product?.ingredients || []
  const waiterOverride = product ? (itemFavorites[product.id] ?? null) : null
  const favorites = product ? buildFavorites(product, waiterOverride) : []

  const unitCfg = product ? (DECIMAL_UNIT_CONFIG[product.unit_type] ?? null) : null
  const isDecimal = !!unitCfg

  const hasTabs = {
    favorites: favorites.length > 0,
    quick: quickOptions.length > 0,
    extras: options.length > 0,
    ingredients: ingredients.length > 0,
    prefs: preferenceSets.length > 0,
    quantity: isDecimal,
  }

  const coursePreselected = initialState?.courseId != null
  // A pref is "mandatory unset" when it has no default and isn't already in favorites
  const prefsMandatoryUnset = hasTabs.prefs && preferenceSets.some(ps => ps.default_choice_id == null)
  const mandatoryPrefInFavorites = prefsMandatoryUnset && preferenceSets
    .filter(ps => ps.default_choice_id == null)
    .every(ps => favorites.some(f => f.type === 'pref' && f.item.id === ps.id))

  const firstTab = (() => {
    // 1. Mandatory pref exists and IS covered by favorites → show favorites
    if (prefsMandatoryUnset && mandatoryPrefInFavorites && hasTabs.favorites) return 'favorites'
    // 2. Mandatory pref exists and NOT in favorites → show prefs
    if (prefsMandatoryUnset && !mandatoryPrefInFavorites) return 'prefs'
    // 3. No mandatory pref → favorites if they exist
    if (hasTabs.favorites) return 'favorites'
    // 4. No favorites, courses enabled and not preselected → courses
    if (courses?.length > 0 && !coursePreselected) return 'courses'
    // 5. Fallback
    return 'notes'
  })()

  const [activeTab, setActiveTab] = useState(firstTab)
  const tabsScrollRef = useRef(null)
  const tabButtonRefs = useRef({})

  // Scroll active tab to center of the tabs bar whenever it changes or the drawer opens
  useEffect(() => {
    if (!isOpen) return
    const id = requestAnimationFrame(() => {
      const bar = tabsScrollRef.current
      const btn = tabButtonRefs.current[activeTab]
      if (!bar || !btn) return
      bar.scrollLeft = btn.offsetLeft - bar.clientWidth / 2 + btn.offsetWidth / 2
    })
    return () => cancelAnimationFrame(id)
  }, [activeTab, isOpen])

  const [qty, setQty] = useState(isDecimal ? (unitCfg?.presets[0] ?? 0.1) : 1)
  const [quickState, setQuickState] = useState({})
  const [extrasState, setExtrasState] = useState({})
  const [expandedExtra, setExpandedExtra] = useState(null)
  const [removedState, setRemovedState] = useState({})
  const [prefs, setPrefs] = useState({})
  const [subChoices, setSubChoices] = useState({})
  const [sharedSubs, setSharedSubs] = useState({})
  const [note, setNote] = useState('')
  const [priceAdj, setPriceAdj] = useState(0)
  const [addAttempted, setAddAttempted] = useState(false)
  const [courseId, setCourseId] = useState(initialState?.courseId ?? null)

  // Reset/init when drawer opens or product changes
  useEffect(() => {
    if (!isOpen || !product) return
    const base = buildInitialState(product)
    if (initialState) {
      setQty(initialState.qty ?? (isDecimal ? (unitCfg?.presets[0] ?? 0.1) : 1))
      setQuickState(initialState.quickState ?? {})
      setExtrasState(initialState.extrasState ?? {})
      setRemovedState(initialState.removedState ?? {})
      setPrefs(initialState.prefs ?? base.prefs)
      setSubChoices(initialState.subChoices ?? base.subChoices)
      setSharedSubs(initialState.sharedSubs ?? base.sharedSubs)
      setNote(initialState.note ?? '')
      setPriceAdj(initialState.priceAdj ?? 0)
      setCourseId(initialState.courseId ?? null)
    } else {
      setQty(isDecimal ? (unitCfg?.presets[0] ?? 0.1) : 1)
      setQuickState({})
      setExtrasState({})
      setRemovedState({})
      setPrefs(base.prefs)
      setSubChoices(base.subChoices)
      setSharedSubs(base.sharedSubs)
      setNote('')
      setPriceAdj(0)
      setCourseId(null)
    }
    setExpandedExtra(null)
    setAddAttempted(false)
    setActiveTab(initialState?.activeTab ?? firstTab)
  }, [isOpen, product?.id])

  // Derived: summary lines + price
  const { summaryLines, totalPrice } = (() => {
    if (!product) return { summaryLines: [], totalPrice: 0 }
    let price = product.base_price
    const lines = []

    preferenceSets.forEach(ps => {
      const choice = prefs[ps.id]
      if (!choice) return
      const inlineSub = choice.sub_choices?.length > 0 ? (subChoices[choice.id] ?? null) : null
      const sharedSub = (ps.shared_subset?.choices?.length > 0 && !choice.disables_subset) ? (sharedSubs[ps.id] ?? null) : null
      const delta = (choice.extra_cost ?? 0) + (inlineSub?.extra_cost ?? 0) + (sharedSub?.extra_cost ?? 0)

      // Skip if this is entirely the default selection
      const defaultChoice = ps.default_choice_id != null ? ps.choices.find(c => c.id === ps.default_choice_id) : null
      const isDefaultChoice = defaultChoice && choice.id === defaultChoice.id
      const defaultInlineSub = isDefaultChoice && defaultChoice.sub_choices?.length > 0
        ? (defaultChoice.sub_choices.find(s => s.is_default) ?? defaultChoice.sub_choices[0])
        : null
      const defaultSharedSub = isDefaultChoice && ps.shared_subset?.choices?.length > 0 && !choice.disables_subset
        ? (ps.shared_subset.choices.find(s => s.is_default) ?? ps.shared_subset.choices[0])
        : null
      const isFullyDefault = isDefaultChoice
        && (!inlineSub || inlineSub.name === defaultInlineSub?.name)
        && (!sharedSub || sharedSub.name === defaultSharedSub?.name)
      if (isFullyDefault) { price += delta; return }

      const value = `${choice.name}${inlineSub ? ` · ${inlineSub.name}` : ''}${sharedSub ? ` · ${sharedSub.name}` : ''}`
      lines.push({ group: 'prefs', label: ps.name, value, qty: 1, price: delta, detail: null })
      price += delta
    })

    quickOptions.forEach(opt => {
      const q = quickState[opt.id] || 0
      if (q === 0) return
      const linePrice = opt.price * q
      lines.push({ group: 'quick', label: opt.name, qty: q, price: linePrice, detail: null })
      price += linePrice
    })

    options.forEach(opt => {
      const sel = extrasState[opt.id]
      if (!sel) return
      if (opt.multi_select && opt.sub_choices?.length > 0) {
        // Each selected sub-choice is its own line in the summary
        const subs = sel.subs ?? {}
        Object.entries(subs).forEach(([subName, subQty]) => {
          if (!subQty || subQty < 1) return
          const sub = opt.sub_choices.find(s => s.name === subName)
          const linePrice = ((opt.extra_cost ?? 0) + (sub?.extra_cost ?? 0)) * subQty
          lines.push({ group: 'extras', label: opt.name, qty: subQty, price: linePrice, subName, detail: null })
          price += linePrice
        })
      } else {
        const sub = opt.sub_choices?.find(s => s.name === sel.subName)
        const linePrice = ((opt.extra_cost ?? 0) + (sub?.extra_cost ?? 0)) * sel.qty
        lines.push({ group: 'extras', label: opt.name, qty: sel.qty, price: linePrice, subName: sub?.name ?? null, detail: null })
        price += linePrice
      }
    })

    ingredients.forEach(ing => {
      if (removedState[ing.id]) lines.push({ group: 'removed', label: ing.name, qty: 1, price: 0, detail: null })
    })

    return { summaryLines: lines, totalPrice: (price + priceAdj) * qty }
  })()

  // Validation
  function isPrefComplete(ps) {
    const choice = prefs[ps.id]
    if (!choice) return false
    if (choice.sub_choices?.length > 0 && subChoices[choice.id] == null) return false
    if (ps.shared_subset?.choices?.length > 0 && !choice.disables_subset && sharedSubs[ps.id] == null) return false
    return true
  }
  const allPrefsOk = preferenceSets.every(isPrefComplete)
  const extrasSubsMissing = options.some(opt => {
    const sel = extrasState[opt.id]
    if (!sel) return false
    // multi-select: no mandatory sub required (waiter can select any combo)
    if (opt.multi_select) return false
    return opt.sub_choices?.length > 0 && sel.subName == null
  })
  const canAdd = allPrefsOk && !extrasSubsMissing

  const prefsHasMandatory = hasTabs.prefs && preferenceSets.some(ps => ps.default_choice_id == null)
  const prefsTabAlert = hasTabs.prefs && !allPrefsOk && (addAttempted || prefsHasMandatory)

  // Also alert the favorites tab if it contains an incomplete pref
  const favHasIncompletePref = hasTabs.favorites && !allPrefsOk && favorites.some(f => f.type === 'pref' && !isPrefComplete(f.item))
  const favTabAlert = favHasIncompletePref && (addAttempted || prefsHasMandatory)

  function handleAdd() {
    if (!canAdd) {
      setAddAttempted(true)
      if (!allPrefsOk) {
        // Jump to favorites if the incomplete pref is there, else prefs tab
        if (favHasIncompletePref) setActiveTab('favorites')
        else if (hasTabs.prefs) setActiveTab('prefs')
      }
      return
    }

    const prefChoices = preferenceSets.flatMap(ps => {
      const choice = prefs[ps.id]
      if (!choice) return []
      const inlineSub = choice.sub_choices?.length > 0 ? (subChoices[choice.id] ?? null) : null
      const sharedSub = ps.shared_subset?.choices?.length > 0 && !choice.disables_subset ? (sharedSubs[ps.id] ?? null) : null

      // Don't emit entries that are entirely at their defaults — nothing changed
      const defaultChoice = ps.default_choice_id != null ? ps.choices.find(c => c.id === ps.default_choice_id) : null
      const isDefaultChoice = defaultChoice && choice.id === defaultChoice.id
      const defaultInlineSub = isDefaultChoice && defaultChoice.sub_choices?.length > 0
        ? (defaultChoice.sub_choices.find(s => s.is_default) ?? defaultChoice.sub_choices[0])
        : null
      const defaultSharedSub = isDefaultChoice && ps.shared_subset?.choices?.length > 0 && !choice.disables_subset
        ? (ps.shared_subset.choices.find(s => s.is_default) ?? ps.shared_subset.choices[0])
        : null
      const isFullyDefault = isDefaultChoice
        && (!inlineSub || inlineSub.name === defaultInlineSub?.name)
        && (!sharedSub || sharedSub.name === defaultSharedSub?.name)
      if (isFullyDefault) return []

      const entries = [{ id: choice.id, name: choice.name, price_delta: choice.extra_cost ?? 0, type: 'pref' }]
      if (inlineSub) entries.push({ id: null, name: inlineSub.name, price_delta: inlineSub.extra_cost ?? 0, type: 'pref_sub' })
      if (sharedSub) entries.push({ id: null, name: sharedSub.name, price_delta: sharedSub.extra_cost ?? 0, type: 'pref_sub' })
      return entries
    })

    const optionEntries = options.flatMap(opt => {
      const sel = extrasState[opt.id]
      if (!sel) return []
      if (opt.multi_select && opt.sub_choices?.length > 0) {
        const subs = sel.subs ?? {}
        return Object.entries(subs).flatMap(([subName, subQty]) => {
          if (!subQty || subQty < 1) return []
          const sub = opt.sub_choices.find(s => s.name === subName)
          const entries = []
          for (let i = 0; i < subQty; i++) {
            entries.push({ id: opt.id, name: opt.name, price_delta: opt.extra_cost ?? 0, type: 'extra' })
            if (sub) entries.push({ id: null, name: sub.name, price_delta: sub.extra_cost ?? 0, type: 'extra_sub' })
          }
          return entries
        })
      }
      const sub = opt.sub_choices?.find(s => s.name === sel.subName)
      const entries = []
      for (let i = 0; i < sel.qty; i++) {
        entries.push({ id: opt.id, name: opt.name, price_delta: opt.extra_cost ?? 0, type: 'extra' })
        if (sub) entries.push({ id: null, name: sub.name, price_delta: sub.extra_cost ?? 0, type: 'extra_sub' })
      }
      return entries
    })

    const quickEntries = quickOptions.flatMap(opt => {
      const q = quickState[opt.id] || 0
      if (q === 0) return []
      return Array.from({ length: q }, () => ({ id: null, name: opt.name, price_delta: opt.price ?? 0, type: 'quick' }))
    })

    const removedNames = ingredients.filter(ing => removedState[ing.id]).map(ing => ing.name)

    onAdd({
      product_id: product.id,
      quantity: qty,
      selected_options: [...prefChoices, ...quickEntries, ...optionEntries],
      removed_ingredients: removedNames,
      notes: note,
      price_adjustment: priceAdj !== 0 ? priceAdj : undefined,
      course_id: courseId ?? undefined,
      _drawerState: { qty, quickState, extrasState, removedState, prefs, subChoices, sharedSubs, note, priceAdj, courseId },
    })
    onClose()
  }

  // Tabs definition — ordered, with SVG icons
  const TAB_ICON = {
    favorites: <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>,
    quick:     <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>,
    extras:    <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/><path d="M12 8v8M8 12h8" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>,
    ingredients: <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/><path d="M8 12h8" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>,
    prefs:     <svg width="14" height="14" viewBox="0 -0.5 21 21" fill="currentColor" style={{ width: 14, height: 14, flexShrink: 0 }}><path d="M12.9,9 L12.9,0 L10.8,0 L10.8,9 L8.7,9 L8.7,11 L10.8,11 L10.8,20 L12.9,20 L12.9,11 L15,11 L15,9 L12.9,9 Z M5.55,0 L3.45,0 L3.45,4 L1.35,4 L1.35,6 L3.45,6 L3.45,20 L5.55,20 L5.55,6 L7.65,6 L7.65,4 L5.55,4 L5.55,0 Z M18.2,9 L20.3,9 L20.3,11 L18.2,11 L18.2,20 L16.1,20 L16.1,11 L14,11 L14,9 L16.1,9 L16.1,0 L18.2,0 L18.2,9 Z"/></svg>,
    quantity:  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M16 16l3-8 3.001 8A5.002 5.002 0 0116 16z"/><path d="M2 16l3-8 3.001 8A5.002 5.002 0 012 16z"/><path d="M7 21h10"/><path d="M12 3v18"/><path d="M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2"/></svg>,
    courses:   <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><ellipse cx="12" cy="18" rx="9" ry="2.5" stroke="currentColor" strokeWidth="2"/><path d="M3 18V8c0-2.5 4-4.5 9-4.5s9 2 9 4.5v10" stroke="currentColor" strokeWidth="2"/><path d="M3 12c0 1.5 4 3 9 3s9-1.5 9-3" stroke="currentColor" strokeWidth="2"/></svg>,
    notes:     <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/><path d="M14 2v6h6M8 13h8M8 17h5" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>,
    price_adjust: <svg width="14" height="14" viewBox="0 0 512 512" fill="currentColor" style={{ width: 14, height: 14, flexShrink: 0 }}><path d="M433.156,104.281l-12.969-5.469c-21.297-9-43.453-13.5-65.844-13.5c-64.766,0-124.234,37.531-152.813,95.047h216l-13.328,64.484H184c-0.266,3.656-0.422,7.406-0.422,11.156c0,9.219,0.813,18.594,2.375,28.031h210.266l-13.25,64.5H211.063c31.344,48.734,84.719,78.25,143.281,78.25c19.859,0,39.781-3.625,59.188-10.875l15.469-5.75v90.734l-8.484,2.266c-21.75,5.875-44.031,8.844-66.172,8.844c-105.422,0-200.266-65.344-238.375-163.469H61.422v-64.5h38.688c-1.188-9.875-1.766-19.094-1.766-28.031c0-3.688,0.094-7.5,0.25-11.156H61.422v-64.484h48.672C143.141,73.75,242.313,0,354.344,0c29.75,0,58.969,5.234,86.938,15.438l9.297,3.438L433.156,104.281z"/></svg>,
    summary:   <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2M9 12h6M9 16h4" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>,
  }
  const tabs = [
    hasTabs.favorites    && { id: 'favorites',    label: 'Αγαπημένα' },
    hasTabs.quick        && { id: 'quick',         label: 'Γρήγορες' },
    hasTabs.extras       && { id: 'extras',        label: 'Έξτρα' },
    hasTabs.ingredients  && { id: 'ingredients',   label: 'Υλικά' },
    hasTabs.prefs        && { id: 'prefs',         label: 'Επιλογές' },
    hasTabs.quantity     && { id: 'quantity',       label: `Ποσότητα (${unitCfg?.label})` },
    (courses?.length > 0) && { id: 'courses',      label: 'Courses' },
    { id: 'notes',         label: 'Σημείωση' },
    priceAdjAllowed      && { id: 'price_adjust',  label: 'Τιμή' },
    { id: 'summary',       label: 'Σύνοψη' },
  ].filter(Boolean)

  const badgeFor = id => {
    if (id === 'favorites') {
      // count favorited items that have been interacted with
      const favQuick = favorites.filter(f => f.type === 'quick' && (quickState[f.item.id] || 0) > 0).length
      const favIng = favorites.filter(f => f.type === 'ingredient' && removedState[f.item.id]).length
      const favExt = favorites.filter(f => f.type === 'option' && extrasState[f.item.id]).length
      const favPref = favorites.filter(f => f.type === 'pref' && isPrefComplete(f.item)).length
      return favQuick + favIng + favExt + favPref
    }
    if (id === 'quick') return Object.values(quickState).filter(v => v > 0).length
    if (id === 'extras') return Object.values(extrasState).filter(Boolean).length
    if (id === 'ingredients') return Object.values(removedState).filter(Boolean).length
    if (id === 'prefs') return preferenceSets.filter(isPrefComplete).length
    if (id === 'courses') return courseId != null ? 1 : 0
    if (id === 'notes') return note ? 1 : 0
    if (id === 'price_adjust') return priceAdj !== 0 ? 1 : 0
    if (id === 'summary') return summaryLines.length + (note ? 1 : 0) + (priceAdj !== 0 ? 1 : 0)
    return 0
  }

  if (!product) return null

  return (
    <>
      {/* Backdrop */}
      <div onClick={onClose} style={{
        position: 'fixed', inset: 0,
        background: 'rgba(0,0,0,0.6)',
        opacity: isOpen ? 1 : 0,
        pointerEvents: isOpen ? 'auto' : 'none',
        transition: 'opacity 260ms ease',
        zIndex: 40,
      }} />

      {/* Sheet */}
      <div style={{
        position: 'fixed', left: 0, right: 0, bottom: 0,
        height: '92svh',
        background: 'var(--bg)',
        borderRadius: '20px 20px 0 0',
        transform: isOpen ? 'translateY(0)' : 'translateY(100%)',
        transition: 'transform 320ms cubic-bezier(0.32, 0.72, 0, 1)',
        zIndex: 41,
        display: 'flex', flexDirection: 'column',
        overflow: 'hidden',
        boxShadow: '0 -4px 20px rgba(0,0,0,0.4)',
      }}>
        {/* Grab handle */}
        <div style={{ padding: '10px 0 4px', display: 'flex', justifyContent: 'center', flexShrink: 0 }}>
          <div style={{ width: 40, height: 4, borderRadius: 2, background: 'var(--border)' }} />
        </div>

        {/* Header */}
        <div style={{ padding: '4px 16px 0', display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0 }}>
          {product.image_url && (
            <img src={product.image_url} alt=""
              style={{ width: 48, height: 48, borderRadius: 12, objectFit: 'cover', flexShrink: 0 }} />
          )}
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 18, fontWeight: 700, color: 'var(--text)', lineHeight: 1.2 }}>{product.name}</div>
            <div style={{ fontSize: 13, color: priceAdj !== 0 ? '#f59e0b' : 'var(--muted)', marginTop: 2 }}>
              {priceAdj !== 0
                ? <><span style={{ textDecoration: 'line-through', opacity: 0.5 }}>{product.base_price.toFixed(2)}</span> → {(product.base_price + priceAdj).toFixed(2)} €</>
                : <>{product.base_price.toFixed(2)} €</>
              }
            </div>
          </div>
          <button onClick={onClose} style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--bg3)', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M6 6L18 18M6 18L18 6" stroke="var(--text)" strokeWidth="2.2" strokeLinecap="round"/></svg>
          </button>
        </div>

        {/* Tabs bar */}
        <div ref={tabsScrollRef} style={{ marginTop: 12, borderBottom: '1px solid var(--border)', overflowX: 'auto', scrollbarWidth: 'none', flexShrink: 0 }}>
          <div style={{ display: 'flex', padding: '0 12px', gap: 2, minWidth: 'max-content' }}>
            {tabs.map(t => {
              const active = activeTab === t.id
              const badge = badgeFor(t.id)
              const isAlert = (t.id === 'prefs' && prefsTabAlert) || (t.id === 'favorites' && favTabAlert)
              const tabColor = isAlert ? '#f87171' : active ? '#f59e0b' : 'var(--muted)'
              return (
                <button key={t.id} ref={el => { tabButtonRefs.current[t.id] = el }} onClick={() => setActiveTab(t.id)} style={{
                  padding: '12px 6px',
                  background: 'none', border: 'none',
                  borderBottom: `2px solid ${active ? '#f59e0b' : isAlert ? '#f87171' : 'transparent'}`,
                  color: tabColor,
                  fontSize: 13, fontWeight: (active || isAlert) ? 700 : 500,
                  fontFamily: 'inherit', cursor: 'pointer',
                  display: 'inline-flex', alignItems: 'center', gap: 5,
                  whiteSpace: 'nowrap', marginRight: 8,
                  transition: isAlert ? 'none' : 'color 120ms ease, border-color 120ms ease',
                  animation: isAlert ? 'tab-alert 1.2s ease-in-out infinite' : 'none',
                }}>
                  {TAB_ICON[t.id] && <span style={{ display: 'inline-flex', alignItems: 'center', opacity: active || isAlert ? 1 : 0.7 }}>{TAB_ICON[t.id]}</span>}
                  {t.label}
                  {badge > 0 && !isAlert && (
                    <span style={{
                      minWidth: 18, height: 18, padding: '0 5px',
                      borderRadius: 9,
                      background: active ? 'var(--accent)' : 'var(--bg3)',
                      color: active ? 'var(--accent-fg)' : 'var(--muted)',
                      fontSize: 11, fontWeight: 700,
                      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                      fontVariantNumeric: 'tabular-nums',
                    }}>{badge}</span>
                  )}
                </button>
              )
            })}
          </div>
        </div>

        {/* Scrollable content */}
        <div style={{ flex: 1, overflowY: 'auto', padding: '16px 16px 20px', background: 'var(--bg)', WebkitOverflowScrolling: 'touch' }}>
          {activeTab === 'favorites' && (
            <FavoritesTab
              product={product}
              waiterOverride={waiterOverride}
              quickState={quickState} setQuickState={setQuickState}
              extrasState={extrasState} setExtrasState={setExtrasState}
              expandedExtra={expandedExtra} setExpandedExtra={setExpandedExtra}
              removedState={removedState} setRemovedState={setRemovedState}
              prefs={prefs} setPrefs={setPrefs}
              subChoices={subChoices} setSubChoices={setSubChoices}
              sharedSubs={sharedSubs} setSharedSubs={setSharedSubs}
            />
          )}
          {activeTab === 'quick' && <QuickTab product={product} quickState={quickState} setQuickState={setQuickState} />}
          {activeTab === 'extras' && <ExtrasTab product={product} extrasState={extrasState} setExtrasState={setExtrasState} expandedExtra={expandedExtra} setExpandedExtra={setExpandedExtra} />}
          {activeTab === 'ingredients' && <IngredientsTab product={product} removedState={removedState} setRemovedState={setRemovedState} />}
          {activeTab === 'prefs' && <PrefsTab product={product} prefs={prefs} setPrefs={setPrefs} subChoices={subChoices} setSubChoices={setSubChoices} sharedSubs={sharedSubs} setSharedSubs={setSharedSubs} />}
          {activeTab === 'quantity' && isDecimal && <QuantityTab unitCfg={unitCfg} qty={qty} setQty={setQty} />}
          {activeTab === 'courses' && courses?.length > 0 && <CoursesTab courses={courses} courseId={courseId} setCourseId={setCourseId} />}
          {activeTab === 'notes' && <NotesTab note={note} setNote={setNote} quickNotes={quickNotes ?? FALLBACK_QUICK_NOTES} />}
          {activeTab === 'price_adjust' && <PriceAdjustTab basePrice={product.base_price} priceAdj={priceAdj} setPriceAdj={setPriceAdj} />}
          {activeTab === 'summary' && <SummaryTab product={product} summaryLines={summaryLines} note={note} onJumpTab={setActiveTab} />}
        </div>

        {/* Footer: qty stepper + ΠΡΟΣΘΗΚΗ */}
        <div style={{ padding: '12px 16px 20px', background: 'var(--bg2)', borderTop: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0, boxShadow: '0 -4px 16px rgba(0,0,0,0.3)' }}>
          {isDecimal ? (
            <div
              onClick={() => setActiveTab('quantity')}
              style={{ display: 'inline-flex', alignItems: 'center', height: 52, borderRadius: 26, background: 'var(--bg3)', border: '1px solid var(--border)', overflow: 'hidden', flexShrink: 0, cursor: 'pointer', padding: '0 16px', gap: 6 }}
            >
              <span style={{ fontSize: 17, fontWeight: 700, color: 'var(--text)', fontVariantNumeric: 'tabular-nums' }}>{fmtDecimalQty(qty, unitCfg)}</span>
              <span style={{ fontSize: 13, fontWeight: 500, color: 'var(--muted)' }}>{unitCfg.label}</span>
            </div>
          ) : (
          <div style={{ display: 'inline-flex', alignItems: 'center', height: 52, borderRadius: 26, background: 'var(--bg3)', border: '1px solid var(--border)', overflow: 'hidden', flexShrink: 0 }}>
            <button onClick={() => setQty(q => Math.max(1, q - 1))} style={{ width: 52, height: 52, border: 'none', background: 'transparent', fontSize: 22, fontWeight: 500, cursor: qty <= 1 ? 'default' : 'pointer', color: qty <= 1 ? 'var(--muted)' : 'var(--text)' }}>−</button>
            <div style={{ minWidth: 32, textAlign: 'center', fontSize: 17, fontWeight: 700, color: 'var(--text)', fontVariantNumeric: 'tabular-nums' }}>{qty}</div>
            <button onClick={() => setQty(q => q + 1)} style={{ width: 52, height: 52, border: 'none', background: 'transparent', fontSize: 22, fontWeight: 500, cursor: 'pointer', color: 'var(--text)' }}>+</button>
          </div>
          )}
          <button onClick={handleAdd} disabled={!canAdd} style={{
            flex: 1, height: 52, borderRadius: 26,
            background: canAdd ? 'var(--accent)' : 'var(--bg3)',
            border: 'none', color: canAdd ? 'var(--accent-fg)' : 'var(--muted)',
            fontSize: 16, fontWeight: 700, fontFamily: 'inherit',
            cursor: canAdd ? 'pointer' : 'not-allowed',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '0 20px',
            transition: 'background 150ms ease',
          }}>
            <span>ADD</span>
            <span style={{ fontVariantNumeric: 'tabular-nums' }}>{totalPrice.toFixed(2)} €</span>
          </button>
        </div>
      </div>
    </>
  )
}
