import { useState, useEffect, useRef, useMemo } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import {
  MapPin, Search, Leaf, X, Plus, ShoppingBag,
  ChevronLeft, ArrowRight, Send, Loader2, Info,
  Armchair, Check, SearchX, UtensilsCrossed, AlertCircle,
  Soup, Salad, Wheat, IceCream2, Wine,
} from 'lucide-react'
import { fetchMenu, submitOrder } from '../api'
import {
  DishArt, Badge, DietChip, TagIcons, Price, DiscountFlag, Stepper,
  eur, discountedPrice, discountPct,
} from '../components/primitives'

// TODO: Replace with real data from API once backend includes restaurant info
const RESTAURANT_FALLBACK = {
  name: 'Our Menu',
  tagline: { en: 'Kitchen & Bar', gr: 'Κουζίνα & Μπαρ' },
  blurb: { en: 'Fresh seasonal plates, served with care.', gr: 'Εποχιακά πιάτα, με αγάπη.' },
  hours: { en: 'Open today · 12:00 – 23:30', gr: 'Ανοιχτά σήμερα · 12:00 – 23:30' },
  location: { en: '', gr: '' },
}

// Category glyph icons — mapped by category id or index
const GLYPH_BY_ID = { starters: Soup, salads: Salad, mains: UtensilsCrossed, sides: Wheat, desserts: IceCream2, drinks: Wine }
const GLYPH_FALLBACK = [Soup, Salad, UtensilsCrossed, Wheat, IceCream2, Wine]
const CATEGORY_HUES = [96, 78, 18, 40, 340, 176]

// Allergen label fallbacks
const ALLERGEN_EN = { gluten: 'gluten', dairy: 'dairy', egg: 'egg', fish: 'fish', shellfish: 'shellfish', nuts: 'nuts', soy: 'soy', sesame: 'sesame', sulphites: 'sulphites' }

const I18N = {
  en: {
    searchPlaceholder: 'Search the menu…',
    add: 'Add', back: 'Back', total: 'Total',
    yourOrder: 'Your order', emptyCart: 'Your cart is empty',
    emptyCartSub: 'Add a few dishes to get started.',
    continue: 'Continue', placeOrder: 'Place order', sending: 'Sending…',
    orderPlaced: 'Order placed!', orderPlacedSub: 'Your order has been sent to the kitchen.',
    newOrder: 'Back to menu', table: 'Table no.', name: 'Your name',
    namePh: 'e.g. Alex', tablePh: 'e.g. 12', orderSummary: 'Order summary',
    contains: 'Contains', ingredients: 'Ingredients', noResults: 'No dishes found',
    noResultsSub: 'Try a different search.',
    popular: 'Popular', chefs: "Chef's pick", off: 'OFF',
    dietary: { vegan: 'Vegan', vegetarian: 'Vegetarian', 'gluten-free': 'Gluten-free', spicy: 'Spicy' },
  },
  gr: {
    searchPlaceholder: 'Αναζήτηση στο μενού…',
    add: 'Προσθήκη', back: 'Πίσω', total: 'Σύνολο',
    yourOrder: 'Η παραγγελία σου', emptyCart: 'Το καλάθι σου είναι άδειο',
    emptyCartSub: 'Πρόσθεσε μερικά πιάτα για να ξεκινήσεις.',
    continue: 'Συνέχεια', placeOrder: 'Αποστολή παραγγελίας', sending: 'Αποστολή…',
    orderPlaced: 'Η παραγγελία στάλθηκε!', orderPlacedSub: 'Η παραγγελία σου εστάλη στην κουζίνα.',
    newOrder: 'Πίσω στο μενού', table: 'Τραπέζι', name: 'Το όνομά σου',
    namePh: 'π.χ. Αλέξης', tablePh: 'π.χ. 12', orderSummary: 'Σύνοψη παραγγελίας',
    contains: 'Περιέχει', ingredients: 'Συστατικά', noResults: 'Δεν βρέθηκαν πιάτα',
    noResultsSub: 'Δοκίμασε διαφορετική αναζήτηση.',
    popular: 'Δημοφιλές', chefs: 'Επιλογή Σεφ', off: 'ΕΚΠΤΩΣΗ',
    dietary: { vegan: 'Vegan', vegetarian: 'Χορτοφαγικό', 'gluten-free': 'Χωρίς γλουτένη', spicy: 'Πικάντικο' },
  },
}

// ── Normalise a backend product to the shape the UI expects ──────────────────
function normaliseProduct(p, catId) {
  return {
    ...p,
    id: String(p.id),
    cat: catId,
    name: p.digital_name || p.name || '',
    desc: p.digital_description || p.description || '',
    price: p.digital_price ?? p.base_price ?? 0,
    badge: p.digital_badge || p.badge || null,
    tags: p.digital_tags || p.tags || [],
    allergens: p.allergens || [],
    ingredients: p.ingredients || null,
    discountPct: p.digital_discount || p.discountPct || 0,
    image_url: p.digital_image_url || p.image_url || null,
    digital_available: p.digital_available !== false,
  }
}

function normaliseCategories(rawCats) {
  return rawCats.map((cat, idx) => {
    const id = cat.id ? String(cat.id) : `cat-${idx}`
    return {
      ...cat,
      id,
      hue: cat.hue ?? CATEGORY_HUES[idx % CATEGORY_HUES.length],
      GlyphIcon: GLYPH_BY_ID[id] ?? GLYPH_FALLBACK[idx % GLYPH_FALLBACK.length],
      products: (cat.products || []).map(p => normaliseProduct(p, id)),
    }
  })
}

// ── Bottom Sheet shell ────────────────────────────────────────────────────────
function Sheet({ open, onClose, children, maxH = '88vh' }) {
  if (!open) return null
  return (
    <div className="fixed inset-0 z-50 flex items-end justify-center">
      <div
        className="absolute inset-0 animate-fade bg-[#2d2a1f]/40 backdrop-blur-[2px]"
        onClick={onClose}
      />
      <div
        className="relative z-10 w-full sm:max-w-[960px] animate-slideup overflow-hidden rounded-t-[24px] bg-[#faf7f0] shadow-[0_-12px_40px_-12px_rgba(45,42,31,0.4)]"
        style={{ maxHeight: maxH }}
      >
        {children}
      </div>
    </div>
  )
}

function SheetHandle() {
  return (
    <div className="flex justify-center pt-2.5">
      <div className="h-1 w-10 rounded-full bg-[#ddd5c0]" />
    </div>
  )
}

// ── Hero ──────────────────────────────────────────────────────────────────────
function Hero({ lang, setLang, restaurant }) {
  const r = { ...RESTAURANT_FALLBACK, ...restaurant }
  return (
    <header className="relative px-6 pt-7 pb-6 text-center">
      {/* Language toggle */}
      <div className="absolute right-5 top-6">
        <div className="flex items-center rounded-full bg-white/70 p-0.5 text-[11px] font-semibold ring-1 ring-[#e3dcc9] backdrop-blur">
          {['en', 'gr'].map(l => (
            <button
              key={l}
              onClick={() => setLang(l)}
              className={`rounded-full px-2.5 py-1 uppercase tracking-wider transition ${
                lang === l ? 'bg-[#2d3b2d] text-[#f0e9d6]' : 'text-[#8a8266]'
              }`}
            >
              {l === 'en' ? 'EN' : 'ΕΛ'}
            </button>
          ))}
        </div>
      </div>

      {r.location?.[lang] && (
        <div className="mx-auto inline-flex items-center gap-1.5 rounded-full bg-white/60 px-3 py-1 text-[10px] font-semibold uppercase tracking-[0.22em] text-[#8a7f5e] ring-1 ring-[#e8e1d1]">
          <MapPin className="h-3 w-3" strokeWidth={2} />
          {r.location[lang]}
        </div>
      )}

      {r.headerImageUrl ? (
        <img
          src={r.headerImageUrl}
          alt={r.name}
          className="mx-auto mt-4 block max-w-[80%] max-h-[120px] w-auto object-contain"
        />
      ) : (
        <h1 className="mt-4 font-display text-[42px] font-semibold leading-[0.95] tracking-tight text-[#2d3b2d]">
          {r.name}
        </h1>
      )}
      <div className="mt-1.5 font-sans text-[14px] font-medium uppercase tracking-[0.18em] text-[#9caf88]">
        {r.tagline?.[lang] ?? r.tagline ?? ''}
      </div>

      {/* Ornament */}
      <div className="mx-auto my-4 flex w-40 items-center gap-2">
        <span className="h-px flex-1 bg-gradient-to-r from-transparent to-[#d8cfb6]" />
        <Leaf className="h-3.5 w-3.5 text-[#c9a24b]" strokeWidth={1.6} />
        <span className="h-px flex-1 bg-gradient-to-l from-transparent to-[#d8cfb6]" />
      </div>

      <p className="mx-auto max-w-[300px] text-[13px] leading-relaxed text-[#7d7660]">
        {r.blurb?.[lang] ?? r.blurb ?? ''}
      </p>

      {r.hours?.[lang] && (
        <div className="mt-2.5 inline-flex items-center gap-1.5 text-[12px] font-medium text-[#3f7d4e]">
          <span className="relative flex h-1.5 w-1.5">
            <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#3f7d4e] opacity-60" />
            <span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-[#3f7d4e]" />
          </span>
          {r.hours[lang]}
        </div>
      )}
    </header>
  )
}

// ── Category Bar ──────────────────────────────────────────────────────────────
function CategoryBar({ categories, active, onPick, onSearch, lang }) {
  const [scrolled, setScrolled] = useState(false)
  const railRef = useRef(null)

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 220)
    window.addEventListener('scroll', onScroll, { passive: true })
    return () => window.removeEventListener('scroll', onScroll)
  }, [])

  useEffect(() => {
    const rail = railRef.current
    if (!rail) return
    const el = rail.querySelector(`[data-pill="${active}"]`)
    if (el) {
      const target = el.offsetLeft - rail.clientWidth / 2 + el.clientWidth / 2
      rail.scrollTo({ left: target, behavior: 'smooth' })
    }
  }, [active])

  return (
    <div className={`sticky top-0 z-30 bg-[#faf7f0]/95 backdrop-blur transition-shadow ${scrolled ? 'shadow-[0_6px_20px_-12px_rgba(45,59,45,0.35)]' : ''}`}>
      <div className="flex items-center gap-2 px-3 py-2.5">
        <button
          onClick={onSearch}
          aria-label="Search"
          className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-white text-[#2d3b2d] ring-1 ring-[#e8e1d1] transition active:scale-90"
        >
          <Search className="h-[18px] w-[18px]" strokeWidth={1.9} />
        </button>
        <div ref={railRef} className="flex gap-1.5 overflow-x-auto no-scrollbar py-[3px]">
          {categories.map(cat => {
            const on = cat.id === active
            const label = typeof cat.name === 'object' ? (cat.name[lang] ?? cat.name.en) : cat.name
            return (
              <button
                key={cat.id}
                data-pill={cat.id}
                onClick={() => onPick(cat.id)}
                className={`whitespace-nowrap rounded-full px-3.5 py-1.5 text-[13px] font-medium transition ${
                  on
                    ? 'bg-[#2d3b2d] text-[#f0e9d6] shadow-sm'
                    : 'bg-white text-[#6d6a59] ring-1 ring-[#e8e1d1]'
                }`}
              >
                {label}
              </button>
            )
          })}
        </div>
      </div>
    </div>
  )
}

// ── Product Card ──────────────────────────────────────────────────────────────
function ProductCard({ product, category, lang, t, onOpen, onAdd, qty, viewOnly }) {
  const name = typeof product.name === 'object' ? (product.name[lang] ?? product.name.en) : product.name
  const desc = typeof product.desc === 'object' ? (product.desc[lang] ?? product.desc.en) : product.desc
  const unavailable = product.digital_available === false

  return (
    <div
      onClick={unavailable ? undefined : () => onOpen(product)}
      className={`group overflow-hidden rounded-[20px] bg-[#fcfbf7] ring-1 ring-[#e7e1d1] shadow-card transition hover:shadow-card-hover active:scale-[0.992] ${unavailable ? 'opacity-50' : 'cursor-pointer'}`}
    >
      <div className="flex items-stretch gap-3.5 p-3.5">
        {/* Left: photo or placeholder art */}
        {product.image_url ? (
          <img
            src={product.image_url}
            alt={name}
            className="w-[100px] min-h-[100px] self-stretch shrink-0 rounded-[13px] object-cover"
          />
        ) : (
          <DishArt product={product} category={category} size="hero" />
        )}

        {/* Right: content column */}
        <div className="flex min-w-0 flex-1 flex-col">
          <div className="flex items-start gap-2">
            <h3 className="min-w-0 flex-1 font-display text-[19px] font-semibold leading-[1.12] tracking-[-0.01em] text-[#2d3b2d]">
              {name}
            </h3>
            <TagIcons product={product} />
          </div>

          <p className="mt-1.5 line-clamp-2 min-h-[2.6em] text-[12.5px] leading-[1.3] text-[#857e69]">
            {desc}
          </p>

          <div className="mt-auto flex items-center justify-between gap-3 border-t border-[#ece4d2] pt-3 mt-3">
            <div className="flex items-center gap-2">
              <Price product={product} large />
              <DiscountFlag product={product} t={t} />
            </div>
            {!viewOnly && (
              <button
                onClick={e => { e.stopPropagation(); if (!unavailable) onAdd(product) }}
                aria-label={t.add}
                className="flex h-8 items-center gap-1 rounded-full bg-[#2d3b2d] pl-2.5 pr-3 text-[12px] font-semibold text-[#f0e9d6] shadow-sm transition active:scale-95 hover:bg-[#26331f]"
              >
                <Plus className="h-4 w-4" strokeWidth={2.4} />
                {qty > 0 ? <span className="tabular-nums">{qty}</span> : t.add}
              </button>
            )}
          </div>
        </div>
      </div>
    </div>
  )
}

// ── Menu Section ──────────────────────────────────────────────────────────────
function Section({ category, lang, t, onOpen, onAdd, cart, sectionRef, viewOnly }) {
  const { hue, products } = category
  const label = typeof category.name === 'object' ? (category.name[lang] ?? category.name.en) : category.name
  return (
    <section ref={sectionRef} data-section={category.id} className="scroll-mt-[64px] px-3 pt-3">
      <div
        className="rounded-[22px] px-3 pb-3 pt-2.5"
        style={{ background: `linear-gradient(180deg, hsl(${hue} 44% 90% / 0.65) 0%, hsl(${hue} 40% 90% / 0) 62%)` }}
      >
        <div className="mb-2.5 flex items-baseline justify-between px-2 pt-1">
          <h2 className="font-sans text-[21px] font-semibold tracking-[-0.01em] text-[#2a2a2a]">{label}</h2>
          <span className="font-sans text-[15px] font-medium tabular-nums text-[#2a2a2a]/45">{products.length}</span>
        </div>
        <div className="flex flex-col gap-3">
          {products.map(p => (
            <ProductCard
              key={p.id}
              product={p}
              category={category}
              lang={lang}
              t={t}
              onOpen={onOpen}
              onAdd={onAdd}
              qty={cart[p.id] || 0}
              viewOnly={viewOnly}
            />
          ))}
        </div>
      </div>
    </section>
  )
}

// ── Product Detail Sheet ──────────────────────────────────────────────────────
function ProductSheet({ product, category, lang, t, onClose, onAdd, qty, onInc, onDec, viewOnly }) {
  if (!product) return null
  const hue = category?.hue ?? 40
  const GlyphIcon = category?.GlyphIcon ?? UtensilsCrossed
  const name = typeof product.name === 'object' ? (product.name[lang] ?? product.name.en) : product.name
  const desc = typeof product.desc === 'object' ? (product.desc[lang] ?? product.desc.en) : product.desc
  const ingredients = product.ingredients
    ? (typeof product.ingredients === 'object' && !Array.isArray(product.ingredients)
        ? (product.ingredients[lang] ?? product.ingredients.en ?? [])
        : product.ingredients)
    : []
  const allergens = product.allergens ?? []
  const badge = product.badge ?? product.digital_badge
  const tags = product.tags ?? product.digital_tags ?? []

  return (
    <Sheet open={!!product} onClose={onClose}>
      <SheetHandle />
      <button
        onClick={onClose}
        className="absolute right-3 top-3 flex h-8 w-8 items-center justify-center rounded-full bg-white/80 text-[#6d6a59] ring-1 ring-[#e8e1d1]"
      >
        <X className="h-4 w-4" strokeWidth={2} />
      </button>
      <div className="max-h-[82vh] overflow-y-auto px-5 pb-5">
        {/* Hero art */}
        {product.image_url ? (
          <div className="mt-2 aspect-square w-full overflow-hidden rounded-2xl">
            <img
              src={product.image_url}
              alt={name}
              className="h-full w-full object-cover"
            />
          </div>
        ) : (
          <div
            className="mt-2 aspect-square w-full flex items-center justify-center overflow-hidden rounded-2xl"
            style={{ background: `linear-gradient(135deg, hsl(${hue} 34% 90%), hsl(${hue} 30% 80%))` }}
          >
            <GlyphIcon
              className="h-16 w-16"
              style={{ color: `hsl(${hue} 32% 42%)`, opacity: 0.6 }}
              strokeWidth={1.2}
            />
          </div>
        )}

        <div className="mt-4 flex flex-wrap items-center gap-2">
          {badge && <Badge kind={badge} t={t} />}
          <DiscountFlag product={product} t={t} />
        </div>
        <h2 className="mt-2 font-display text-[28px] font-semibold leading-tight text-[#2d3b2d]">{name}</h2>
        {desc && <p className="mt-1 text-[14px] leading-relaxed text-[#7d7660]">{desc}</p>}

        {tags.length > 0 && (
          <div className="mt-3 flex flex-wrap gap-1.5">
            {tags.map(tag => <DietChip key={tag} tag={tag} t={t} />)}
          </div>
        )}

        {ingredients.length > 0 && (
          <div className="mt-5">
            <div className="font-sans text-[11px] font-semibold uppercase tracking-[0.14em] text-[#b3aa90]">{t.ingredients}</div>
            <div className="mt-1.5 flex flex-wrap gap-1.5">
              {ingredients.map((ing, i) => (
                <span key={i} className="rounded-lg bg-white px-2.5 py-1 text-[12.5px] text-[#5f5a48] ring-1 ring-[#ece5d5]">{ing}</span>
              ))}
            </div>
          </div>
        )}

        {allergens.length > 0 && (
          <div className="mt-4 flex items-start gap-2 rounded-xl bg-[#f7e6dc]/60 px-3 py-2.5 ring-1 ring-[#eccab3]">
            <Info className="mt-0.5 h-4 w-4 shrink-0 text-[#c2602f]" strokeWidth={2} />
            <div className="text-[12.5px] leading-snug text-[#9a5732]">
              <span className="font-semibold">{t.contains}: </span>
              {allergens.map(a => ALLERGEN_EN[a] ?? a).join(', ')}
            </div>
          </div>
        )}
      </div>

      {/* Sticky add bar */}
      <div className="flex items-center gap-3 border-t border-[#ece5d5] bg-[#faf7f0] px-5 py-3.5">
        {!viewOnly && qty > 0 ? (
          <Stepper qty={qty} onInc={() => onInc(product)} onDec={() => onDec(product)} />
        ) : (
          <div className="flex items-baseline gap-2">
            <Price product={product} large />
            <DiscountFlag product={product} t={t} />
          </div>
        )}
        {!viewOnly && (
          <button
            onClick={() => { onAdd(product); onClose() }}
            className="ml-auto flex h-11 flex-1 items-center justify-center gap-2 rounded-full bg-[#2d3b2d] px-5 text-[14px] font-semibold text-[#f0e9d6] shadow-sm transition active:scale-[0.98] hover:bg-[#26331f]"
          >
            <Plus className="h-4 w-4" strokeWidth={2.4} />
            {t.add} · {eur(discountedPrice(product))}
          </button>
        )}
      </div>
    </Sheet>
  )
}

// ── Search Overlay ────────────────────────────────────────────────────────────
function SearchOverlay({ open, onClose, categories, lang, t, onOpen, onAdd, cart, viewOnly }) {
  const [q, setQ] = useState('')
  const inputRef = useRef(null)
  useEffect(() => { if (open && inputRef.current) inputRef.current.focus() }, [open])
  useEffect(() => { if (!open) setQ('') }, [open])

  const allProducts = useMemo(() => categories.flatMap(c => c.products), [categories])

  const results = useMemo(() => {
    const term = q.trim().toLowerCase()
    if (!term) return []
    return allProducts.filter(p => {
      const name = typeof p.name === 'object' ? Object.values(p.name).join(' ') : (p.name ?? '')
      const desc = typeof p.desc === 'object' ? Object.values(p.desc).join(' ') : (p.desc ?? '')
      const ings = p.ingredients
        ? (Array.isArray(p.ingredients) ? p.ingredients : Object.values(p.ingredients).flat()).join(' ')
        : ''
      return (name + ' ' + desc + ' ' + ings).toLowerCase().includes(term)
    })
  }, [q, allProducts])

  if (!open) return null

  return (
    <div className="fixed inset-0 z-50 mx-auto flex w-full sm:max-w-[960px] flex-col bg-[#faf7f0] animate-fade">
      <div className="flex items-center gap-2 px-3 py-3">
        <div className="flex flex-1 items-center gap-2 rounded-full bg-white px-3.5 py-2.5 ring-1 ring-[#e8e1d1]">
          <Search className="h-[18px] w-[18px] text-[#b3aa90]" strokeWidth={1.9} />
          <input
            ref={inputRef}
            value={q}
            onChange={e => setQ(e.target.value)}
            placeholder={t.searchPlaceholder}
            className="w-full bg-transparent text-[15px] text-[#2d3b2d] outline-none placeholder:text-[#b3aa90]"
          />
          {q && (
            <button onClick={() => setQ('')}>
              <X className="h-4 w-4 text-[#b3aa90]" />
            </button>
          )}
        </div>
        <button onClick={onClose} className="px-1 text-[14px] font-medium text-[#6d6a59]">
          {t.back}
        </button>
      </div>

      <div className="flex-1 overflow-y-auto px-4 pb-6">
        {q && results.length === 0 && (
          <div className="mt-24 text-center">
            <SearchX className="mx-auto h-10 w-10 text-[#cfc6ad]" strokeWidth={1.4} />
            <div className="mt-3 font-display text-[20px] text-[#2d3b2d]">{t.noResults}</div>
            <div className="mt-1 text-[13px] text-[#9a917a]">{t.noResultsSub}</div>
          </div>
        )}
        {results.length > 0 && (
          <div className="flex flex-col gap-3 pt-1">
            {results.map(p => {
              const cat = categories.find(c => c.id === p.cat)
              return (
                <ProductCard
                  key={p.id}
                  product={p}
                  category={cat}
                  lang={lang}
                  t={t}
                  onOpen={prod => { onClose(); onOpen(prod) }}
                  onAdd={onAdd}
                  qty={cart[p.id] || 0}
                  viewOnly={viewOnly}
                />
              )
            })}
          </div>
        )}
        {!q && (
          <div className="mt-24 text-center text-[#b3aa90]">
            <UtensilsCrossed className="mx-auto h-10 w-10" strokeWidth={1.3} />
            <div className="mt-3 text-[13px]">{t.searchPlaceholder}</div>
          </div>
        )}
      </div>
    </div>
  )
}

// ── Cart Flow (bottom sheet) ──────────────────────────────────────────────────
function CartFlow({ stage, setStage, cart, setCart, categories, lang, t, onOpenProduct, siteSlug, navigate }) {
  const [form, setForm] = useState({ name: '', table: '' })
  const [sending, setSending] = useState(false)

  const allProducts = useMemo(() => categories.flatMap(c => c.products), [categories])

  const lines = useMemo(() =>
    Object.entries(cart)
      .map(([id, qty]) => ({ product: allProducts.find(p => p.id === id), qty }))
      .filter(l => l.product && l.qty > 0),
    [cart, allProducts]
  )
  const total = lines.reduce((s, l) => s + discountedPrice(l.product) * l.qty, 0)

  const inc = p => setCart(c => ({ ...c, [p.id]: (c[p.id] || 0) + 1 }))
  const dec = p => setCart(c => {
    const n = (c[p.id] || 0) - 1
    const next = { ...c }
    if (n <= 0) delete next[p.id]; else next[p.id] = n
    return next
  })

  const submit = async () => {
    setSending(true)
    try {
      const result = await submitOrder(siteSlug, {
        order_type: 'dine_in',
        customer_name: form.name.trim(),
        customer_table: form.table.trim(),
        items: lines.map(l => ({
          product_id: l.product.id,
          name: typeof l.product.name === 'object' ? l.product.name.en : l.product.name,
          quantity: l.qty,
          unit_price: discountedPrice(l.product),
        })),
        subtotal: Math.round(total * 100) / 100,
        total: Math.round(total * 100) / 100,
        lang,
        placed_at: new Date().toISOString(),
      })
      setCart({})
      setForm({ name: '', table: '' })
      setStage(null)
      navigate(`/${siteSlug}/confirm/${result.public_ref}`)
    } catch {
      setSending(false)
    }
  }

  const close = () => setStage(null)

  // Cart view
  if (stage === 'cart') {
    return (
      <Sheet open onClose={close}>
        <SheetHandle />
        <div className="flex items-center justify-between px-5 pb-1 pt-3">
          <h2 className="font-display text-[24px] font-semibold text-[#2d3b2d]">{t.yourOrder}</h2>
          <button onClick={close} className="flex h-8 w-8 items-center justify-center rounded-full bg-white text-[#6d6a59] ring-1 ring-[#e8e1d1]">
            <X className="h-4 w-4" strokeWidth={2} />
          </button>
        </div>
        {lines.length === 0 ? (
          <div className="flex flex-col items-center px-6 py-16 text-center">
            <ShoppingBag className="h-12 w-12 text-[#cfc6ad]" strokeWidth={1.3} />
            <div className="mt-4 font-display text-[20px] text-[#2d3b2d]">{t.emptyCart}</div>
            <div className="mt-1 text-[13px] text-[#9a917a]">{t.emptyCartSub}</div>
          </div>
        ) : (
          <>
            <div className="max-h-[56vh] overflow-y-auto px-4 py-3">
              <div className="flex flex-col gap-2.5">
                {lines.map(l => {
                  const cat = categories.find(c => c.id === l.product.cat)
                  const pname = typeof l.product.name === 'object' ? (l.product.name[lang] ?? l.product.name.en) : l.product.name
                  return (
                    <div key={l.product.id} className="flex items-center gap-3 rounded-2xl bg-white p-2.5 ring-1 ring-[#ece5d5]">
                      <DishArt product={l.product} category={cat} size="sm" />
                      <div className="min-w-0 flex-1">
                        <div
                          onClick={() => { close(); onOpenProduct(l.product) }}
                          className="cursor-pointer font-display text-[16px] font-semibold leading-tight text-[#2d3b2d]"
                        >
                          {pname}
                        </div>
                        <div className="mt-0.5 font-display text-[14px] text-[#857e69]">{eur(discountedPrice(l.product))}</div>
                      </div>
                      <Stepper qty={l.qty} onInc={() => inc(l.product)} onDec={() => dec(l.product)} />
                    </div>
                  )
                })}
              </div>
            </div>
            <div className="border-t border-[#ece5d5] px-5 py-3.5">
              <div className="mb-2.5 flex items-baseline justify-between">
                <span className="text-[13px] font-medium text-[#7d7660]">{t.total}</span>
                <span className="font-display text-[24px] font-semibold tabular-nums text-[#2d3b2d]">{eur(total)}</span>
              </div>
              <button
                onClick={() => setStage('checkout')}
                className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-[#2d3b2d] text-[15px] font-semibold text-[#f0e9d6] transition active:scale-[0.98]"
              >
                {t.continue}<ArrowRight className="h-4 w-4" strokeWidth={2.2} />
              </button>
            </div>
          </>
        )}
      </Sheet>
    )
  }

  // Checkout view
  if (stage === 'checkout') {
    const valid = form.name.trim() && form.table.trim()
    return (
      <Sheet open onClose={close}>
        <SheetHandle />
        <div className="flex items-center gap-3 px-5 pb-1 pt-3">
          <button
            onClick={() => setStage('cart')}
            className="flex h-8 w-8 items-center justify-center rounded-full bg-white text-[#6d6a59] ring-1 ring-[#e8e1d1]"
          >
            <ChevronLeft className="h-4 w-4" strokeWidth={2.2} />
          </button>
          <h2 className="font-display text-[22px] font-semibold text-[#2d3b2d]">{t.placeOrder}</h2>
        </div>
        <div className="max-h-[62vh] overflow-y-auto px-5 pb-2 pt-3">
          <div className="grid grid-cols-2 gap-3">
            <label className="block">
              <span className="text-[11px] font-semibold uppercase tracking-[0.12em] text-[#9a917a]">{t.name}</span>
              <input
                value={form.name}
                onChange={e => setForm(f => ({ ...f, name: e.target.value }))}
                placeholder={t.namePh}
                className="mt-1.5 w-full rounded-xl bg-white px-3.5 py-3 text-[15px] text-[#2d3b2d] outline-none ring-1 ring-[#e8e1d1] focus:ring-2 focus:ring-[#9caf88]"
              />
            </label>
            <label className="block">
              <span className="text-[11px] font-semibold uppercase tracking-[0.12em] text-[#9a917a]">{t.table}</span>
              <input
                value={form.table}
                onChange={e => setForm(f => ({ ...f, table: e.target.value }))}
                placeholder={t.tablePh}
                inputMode="numeric"
                className="mt-1.5 w-full rounded-xl bg-white px-3.5 py-3 text-[15px] text-[#2d3b2d] outline-none ring-1 ring-[#e8e1d1] focus:ring-2 focus:ring-[#9caf88]"
              />
            </label>
          </div>

          <div className="mt-5 text-[11px] font-semibold uppercase tracking-[0.12em] text-[#9a917a]">{t.orderSummary}</div>
          <div className="mt-2 overflow-hidden rounded-2xl bg-white ring-1 ring-[#ece5d5]">
            {lines.map((l, i) => {
              const pname = typeof l.product.name === 'object' ? (l.product.name[lang] ?? l.product.name.en) : l.product.name
              return (
                <div key={l.product.id} className={`flex items-center justify-between px-4 py-2.5 ${i > 0 ? 'border-t border-[#f0ebdd]' : ''}`}>
                  <span className="text-[13.5px] text-[#5f5a48]">
                    <b className="font-display text-[#2d3b2d]">{l.qty}×</b> {pname}
                  </span>
                  <span className="font-display text-[14px] font-semibold tabular-nums text-[#2d3b2d]">
                    {eur(discountedPrice(l.product) * l.qty)}
                  </span>
                </div>
              )
            })}
          </div>
        </div>
        <div className="border-t border-[#ece5d5] px-5 py-3.5">
          <div className="mb-2.5 flex items-baseline justify-between">
            <span className="text-[13px] font-medium text-[#7d7660]">{t.total}</span>
            <span className="font-display text-[24px] font-semibold tabular-nums text-[#2d3b2d]">{eur(total)}</span>
          </div>
          <button
            disabled={!valid || sending}
            onClick={submit}
            className={`flex h-12 w-full items-center justify-center gap-2 rounded-full text-[15px] font-semibold transition active:scale-[0.98] ${
              valid && !sending ? 'bg-[#2d3b2d] text-[#f0e9d6]' : 'bg-[#d8d2c1] text-[#a39c87] cursor-not-allowed'
            }`}
          >
            {sending
              ? <><Loader2 className="h-4 w-4 animate-spin" /> {t.sending}</>
              : <><Send className="h-4 w-4" strokeWidth={2} /> {t.placeOrder}</>
            }
          </button>
        </div>
      </Sheet>
    )
  }

  return null
}

// ── Floating Cart Button ──────────────────────────────────────────────────────
function CartButton({ count, total, t, onClick }) {
  const [bump, setBump] = useState(false)
  const prev = useRef(count)
  useEffect(() => {
    if (count !== prev.current && count > 0) {
      setBump(true)
      const tm = setTimeout(() => setBump(false), 320)
      prev.current = count
      return () => clearTimeout(tm)
    }
    prev.current = count
  }, [count])

  if (count === 0) return null
  return (
    <div className="pointer-events-none fixed inset-x-0 bottom-0 z-40 mx-auto w-full sm:max-w-[960px] px-4 pb-4">
      <button
        onClick={onClick}
        className={`pointer-events-auto flex h-14 w-full items-center justify-between rounded-full bg-[#2d3b2d] px-5 text-[#f0e9d6] shadow-cart transition active:scale-[0.98] ${bump ? 'animate-pop' : ''}`}
      >
        <span className="flex items-center gap-2.5">
          <span className="relative">
            <ShoppingBag className="h-[22px] w-[22px]" strokeWidth={1.8} />
            <span className="absolute -right-2 -top-2 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-[#c9a24b] px-1 text-[11px] font-bold text-[#2d3b2d] tabular-nums">
              {count}
            </span>
          </span>
          <span className="text-[14px] font-semibold">{t.yourOrder}</span>
        </span>
        <span className="font-display text-[18px] font-semibold tabular-nums">{eur(total)}</span>
      </button>
    </div>
  )
}

// ── Main MenuPage ─────────────────────────────────────────────────────────────
export default function MenuPage() {
  const { siteSlug } = useParams()
  const navigate = useNavigate()

  const [categories, setCategories] = useState([])
  const [restaurant, setRestaurant] = useState(null)
  const [viewOnly, setViewOnly] = useState(false)
  const [error, setError] = useState(null)
  const [loading, setLoading] = useState(true)

  const [lang, setLang] = useState(() => {
    try { return localStorage.getItem('ot_lang') || 'en' } catch { return 'en' }
  })
  const [cart, setCart] = useState(() => {
    try { return JSON.parse(localStorage.getItem('ot_cart')) || {} } catch { return {} }
  })
  const [active, setActive] = useState(null)
  const [activeProduct, setActiveProduct] = useState(null)
  const [activeProductCat, setActiveProductCat] = useState(null)
  const [searchOpen, setSearchOpen] = useState(false)
  const [stage, setStage] = useState(null)

  const t = I18N[lang] ?? I18N.en

  useEffect(() => { try { localStorage.setItem('ot_lang', lang) } catch {} }, [lang])
  useEffect(() => { try { localStorage.setItem('ot_cart', JSON.stringify(cart)) } catch {} }, [cart])

  useEffect(() => {
    fetchMenu(siteSlug)
      .then(data => {
        const cats = normaliseCategories(data.categories || [])
        setCategories(cats)
        setRestaurant(data.restaurant ?? null)
        setViewOnly(data.menu_mode === 'view_only')
        if (cats.length) setActive(cats[0].id)
      })
      .catch(() => setError('Menu not available. Please try again.'))
      .finally(() => setLoading(false))
  }, [siteSlug])

  const sectionRefs = useRef({})
  const clickLock = useRef(false)

  // Scroll-spy
  useEffect(() => {
    const onScroll = () => {
      if (clickLock.current) return
      let current = categories[0]?.id
      for (const c of categories) {
        const el = sectionRefs.current[c.id]
        if (el && el.getBoundingClientRect().top <= 90) current = c.id
      }
      if (current) setActive(a => a === current ? a : current)
    }
    window.addEventListener('scroll', onScroll, { passive: true })
    onScroll()
    return () => window.removeEventListener('scroll', onScroll)
  }, [categories])

  const pick = id => {
    const el = sectionRefs.current[id]
    if (!el) return
    setActive(id)
    clickLock.current = true
    const top = el.getBoundingClientRect().top + window.scrollY - 64
    window.scrollTo({ top, behavior: 'smooth' })
    setTimeout(() => { clickLock.current = false }, 700)
  }

  const addToCart = p => setCart(c => ({ ...c, [p.id]: (c[p.id] || 0) + 1 }))
  const incCart = p => setCart(c => ({ ...c, [p.id]: (c[p.id] || 0) + 1 }))
  const decCart = p => setCart(c => {
    const n = (c[p.id] || 0) - 1
    const next = { ...c }
    if (n <= 0) delete next[p.id]; else next[p.id] = n
    return next
  })

  const openProduct = p => {
    setActiveProduct(p)
    setActiveProductCat(categories.find(c => c.id === p.cat) ?? null)
  }

  const count = Object.values(cart).reduce((s, q) => s + q, 0)
  const total = useMemo(() => {
    const allProducts = categories.flatMap(c => c.products)
    return Object.entries(cart).reduce((s, [id, q]) => {
      const p = allProducts.find(x => x.id === id)
      return p ? s + discountedPrice(p) * q : s
    }, 0)
  }, [cart, categories])

  if (loading) return (
    <div className="min-h-dvh flex items-center justify-center bg-[#faf7f0]">
      <div className="w-8 h-8 rounded-full border-2 border-[#2d3b2d] border-t-transparent animate-spin" />
    </div>
  )

  if (error) return (
    <div className="min-h-dvh flex flex-col items-center justify-center gap-3 p-8 text-center bg-[#faf7f0]">
      <AlertCircle className="text-[#c2602f]" size={40} />
      <p className="text-[#7d7660]">{error}</p>
    </div>
  )

  return (
    <div className="relative mx-auto min-h-dvh w-full sm:max-w-[960px] bg-[#faf7f0] sm:shadow-[0_0_60px_-20px_rgba(45,42,31,0.3)]">
      <Hero lang={lang} setLang={setLang} restaurant={restaurant} />
      <CategoryBar
        categories={categories}
        active={active}
        onPick={pick}
        onSearch={() => setSearchOpen(true)}
        lang={lang}
      />

      <main className="pb-32">
        {categories.map(cat => (
          <Section
            key={cat.id}
            category={cat}
            lang={lang}
            t={t}
            onOpen={openProduct}
            onAdd={addToCart}
            cart={cart}
            sectionRef={el => { sectionRefs.current[cat.id] = el }}
            viewOnly={viewOnly}
          />
        ))}

        <footer className="mt-10 px-6 text-center">
          <div className="mx-auto flex w-32 items-center gap-2">
            <span className="h-px flex-1 bg-gradient-to-r from-transparent to-[#d8cfb6]" />
            <Leaf className="h-3 w-3 text-[#c9a24b]" strokeWidth={1.6} />
            <span className="h-px flex-1 bg-gradient-to-l from-transparent to-[#d8cfb6]" />
          </div>
        </footer>
      </main>

      {!viewOnly && <CartButton count={count} total={total} t={t} onClick={() => setStage('cart')} />}

      <ProductSheet
        product={activeProduct}
        category={activeProductCat}
        lang={lang}
        t={t}
        onClose={() => setActiveProduct(null)}
        onAdd={addToCart}
        qty={activeProduct ? (cart[activeProduct.id] || 0) : 0}
        onInc={incCart}
        onDec={decCart}
        viewOnly={viewOnly}
      />

      <SearchOverlay
        open={searchOpen}
        onClose={() => setSearchOpen(false)}
        categories={categories}
        lang={lang}
        t={t}
        onOpen={openProduct}
        onAdd={addToCart}
        cart={cart}
        viewOnly={viewOnly}
      />

      {!viewOnly && (
        <CartFlow
          stage={stage}
          setStage={setStage}
          cart={cart}
          setCart={setCart}
          categories={categories}
          lang={lang}
          t={t}
          onOpenProduct={openProduct}
          siteSlug={siteSlug}
          navigate={navigate}
        />
      )}
    </div>
  )
}
