/* ============================================================
   RIVA — Assemblage du site
   ============================================================ */

const { useState: useS, useEffect: useE, useMemo: useM } = React;

function App() {
  const [cart, setCart] = useS([]);
  const [cartOpen, setCartOpen] = useS(false);
  const [checkoutOpen, setCheckoutOpen] = useS(false);
  const [aiOpen, setAiOpen] = useS(false);
  const [phoneOpen, setPhoneOpen] = useS(false);
  const [platAComposer, setPlatAComposer] = useS(null);
  const [adminUnlocked, setAdminUnlocked] = useS(false);
  const [menuVersion, setMenuVersion] = useS(0);
  const [view, setView] = useS('site');
  // Numéro de table lu dans l'adresse (?table=7), retenu pour toute la visite
  const [table, setTable] = useS(() => getTable());

  const bumpMenu = () => setMenuVersion(v => v + 1);

  // Le bandeau vert « table X » est fixé en haut : on décale le reste de la
  // page pour qu'il ne recouvre pas l'en-tête.
  useE(() => {
    document.body.classList.toggle('avec-table', !!table && view === 'site');
  }, [table, view]);

  /* --- Accès au tableau de bord --- */
  useE(() => {
    try {
      const url = new URL(window.location.href);
      const stored = localStorage.getItem('bt-admin-ouvert') === '1';
      if (url.searchParams.has('admin')) {
        url.searchParams.delete('admin');
        window.history.replaceState({}, '', url.toString());
      }
      if (stored && getAdminKey()) {
        setAdminUnlocked(true);
      } else {
        localStorage.removeItem('bt-admin-ouvert');
      }
    } catch (e) {}
  }, []);

  // Appui long de 1,5 s sur le logo : le patron ouvre le tableau de bord.
  // Aucun client ne reste appuyé sur un logo par hasard.
  const longPress = React.useRef({ timer: null, triggered: false });

  const startLongPress = () => {
    longPress.current.triggered = false;
    longPress.current.timer = setTimeout(async () => {
      longPress.current.triggered = true;
      try { if (navigator.vibrate) navigator.vibrate(50); } catch (e) {}
      const key = prompt('Mot de passe du tableau de bord :');
      if (key !== null) {
        try {
          const reponse = await fetch('/api/admin/auth', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ password: key }),
          });
          if (reponse.ok) {
            setAdminKeyValue(key);
            localStorage.setItem('bt-admin-ouvert', '1');
            setAdminUnlocked(true);
            showToast('Tableau de bord ouvert');
            setView('admin');
          } else {
            showToast('Mot de passe incorrect');
          }
        } catch (e) {
          showToast('Connexion au serveur impossible');
        }
      }
    }, 1500);
  };

  const cancelLongPress = () => {
    if (longPress.current.timer) {
      clearTimeout(longPress.current.timer);
      longPress.current.timer = null;
    }
  };

  const onLogoClick = (e) => {
    if (longPress.current.triggered) {
      e?.preventDefault?.();
      e?.stopPropagation?.();
      longPress.current.triggered = false;
      return false;
    }
    return true;
  };

  const lockAdmin = () => {
    localStorage.removeItem('bt-admin-ouvert');
    setAdminKeyValue('');
    setAdminUnlocked(false);
    setView('site');
    showToast('Tableau de bord verrouillé');
  };

  /* --- Panier mémorisé --- */
  useE(() => {
    try {
      const stored = localStorage.getItem('bt-panier');
      if (stored) {
        // On ne garde que les plats de la carte actuelle, avec leur photo du
        // moment : un panier resté d'un autre site, ou un plat retiré de la
        // carte, disparaît au lieu de s'afficher avec un dessin inconnu.
        const plats = Object.values(getEffectiveMenu().menu).flatMap(c => c.items || []);
        const lignes = (JSON.parse(stored) || []).map(l => {
          const id = String(l && l.id || '');
          // Le plat exact, sinon le plus long préfixe (« plat-1712… » = plat composé)
          const plat = plats.find(p => p.id === id) || plats
            .filter(p => id.startsWith(p.id + '-'))
            .sort((a, b) => b.id.length - a.id.length)[0];
          return plat ? { ...l, img: plat.img || l.img } : null;
        }).filter(Boolean);
        setCart(lignes);
      }
    } catch (e) {}
  }, []);
  useE(() => {
    try { localStorage.setItem('bt-panier', JSON.stringify(cart)); } catch (e) {}
  }, [cart]);

  const subtotal = useM(() => cart.reduce((s, it) => s + it.price * it.qty, 0), [cart]);
  const cartCount = useM(() => cart.reduce((s, it) => s + it.qty, 0), [cart]);

  const addToCart = (item) => {
    if (item.rupture) { showToast(`${item.name} : en rupture pour le moment`); return; }
    // Plat avec des choix obligatoires ou plat signature : on ouvre l'écran de composition
    if (shouldUpsell(item)) {
      setPlatAComposer(item);
      return;
    }
    ajouterLignes([{ id: item.id, name: item.name, price: item.price, img: item.img,
                     teinte: item.teinte, catLabel: item.catLabel, qty: 1 }]);
    showToast(`${item.name} ajouté`);
  };

  const ajouterLignes = (lignes) => {
    // Un supplément ou une boisson proposés à côté peuvent être en rupture.
    const ruptures = getRuptures();
    lignes = lignes.filter(l => !ruptures.some(r => l.id === r || String(l.id).startsWith(r + '-')));
    setCart(prev => {
      let next = [...prev];
      lignes.forEach(l => {
        // Une ligne qui porte une remarque (« sans oignons ») reste à part.
        const dejaLa = next.findIndex(x => x.id === l.id && !x.options && !l.options && !x.remarque && !l.remarque);
        if (dejaLa >= 0) next[dejaLa] = { ...next[dejaLa], qty: next[dejaLa].qty + l.qty };
        else next = [...next, l];
      });
      return next;
    });
  };

  const validerComposition = (lignes) => {
    ajouterLignes(lignes);
    const total = lignes.reduce((s, l) => s + l.price * l.qty, 0);
    showToast(`Ajouté · ${total.toFixed(2)}€`);
    setPlatAComposer(null);
    setTimeout(() => setCartOpen(true), 250);
  };

  const updateQty = (i, qty) => {
    if (qty <= 0) return removeItem(i);
    setCart(cart.map((it, idx) => idx === i ? { ...it, qty } : it));
  };
  const removeItem = (i) => setCart(cart.filter((_, idx) => idx !== i));
  // La remarque du client sur UN plat : « sans oignons », « bien cuit »…
  const setRemarque = (i, remarque) => setCart(cart.map((it, idx) => idx === i ? { ...it, remarque: String(remarque || '').slice(0, 120) } : it));
  const clearCart = () => setCart([]);

  const onNav = (id) => {
    if (id === 'top') window.scrollTo({ top: 0, behavior: 'smooth' });
    else document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  const scrollToMenu = () => document.getElementById('menu')?.scrollIntoView({ behavior: 'smooth' });

  const openCheckout = () => {
    if (cart.length === 0) {
      showToast('Votre commande est vide');
      return;
    }
    setCartOpen(false);
    setCheckoutOpen(true);
  };

  const sortirDeLaTable = () => {
    quitterLaTable();
    setTable(null);
    showToast('Vous ne commandez plus pour une table');
  };

  return (
    <>
      {table && view === 'site' && (
        <div className="bandeau-table">
          <span>Vous commandez pour la table {table}</span>
          <button onClick={sortirDeLaTable}>ce n'est pas ma table</button>
        </div>
      )}

      <Header cartCount={cartCount} onCartOpen={() => setCartOpen(true)} onNav={onNav} view={view} setView={setView}
              compact={!!table && view === 'site'}
              adminUnlocked={adminUnlocked}
              onLogoClick={onLogoClick}
              startLongPress={startLongPress}
              cancelLongPress={cancelLongPress}/>

      {view === 'site' && table ? (
        /* Arrivé par le QR d'une table : le client est assis, il a faim et il
           a le menu papier sous les yeux. On lui donne la carte, tout de
           suite, et rien d'autre — pas d'histoire du restaurant, pas
           d'horaires, pas de plan d'accès. */
        <main>
          <Borne addToCart={addToCart} compact/>
          {SHOP.phone && (
            <div className="pb-16 text-center">
              <button onClick={() => setPhoneOpen(true)} className="btn btn-ghost !text-xs">
                Un souci ? Appeler le restaurant
              </button>
            </div>
          )}
        </main>
      ) : view === 'site' ? (
        <main>
          <Hero onScrollToMenu={scrollToMenu} openPhone={() => setPhoneOpen(true)} table={table}/>
          <Ticker/>
          <SignatureFeature addToCart={addToCart}/>
          <HowItWorks/>
          <Borne addToCart={addToCart}/>
          <CommanderSection openCart={() => setCartOpen(true)} openPhone={() => setPhoneOpen(true)}
                            openMenu={scrollToMenu} table={table} cartCount={cartCount}/>
          <Story/>
          <Reviews/>
          <Visit/>
          <Footer/>
        </main>
      ) : (
        <AdminView onClose={() => setView('site')} onLock={lockAdmin} onMenuChange={bumpMenu}/>
      )}

      <CartDrawer
        open={cartOpen}
        onClose={() => setCartOpen(false)}
        cart={cart}
        updateQty={updateQty}
        removeItem={removeItem}
        setRemarque={setRemarque}
        clearCart={clearCart}
        onCheckout={openCheckout}
        subtotal={subtotal}
        table={table}
      />

      <CheckoutModal
        open={checkoutOpen}
        onClose={() => setCheckoutOpen(false)}
        cart={cart}
        subtotal={subtotal}
        clearCart={clearCart}
        table={table}
      />

      <ComposerModal
        open={!!platAComposer}
        item={platAComposer}
        onClose={() => setPlatAComposer(null)}
        onConfirm={validerComposition}
      />

      <PhonePopup open={phoneOpen} onClose={() => setPhoneOpen(false)}/>

      {view === 'site' && <AILauncher onOpen={() => setAiOpen(true)} hidden={aiOpen}/>}
      <AIChat open={aiOpen} onClose={() => setAiOpen(false)}/>

      <ToastContainer/>
    </>
  );
}

// ====== PETITS MESSAGES EN BAS D'ÉCRAN ======
let toastId = 0;
let setToastsFn = null;
function showToast(msg) {
  if (setToastsFn) setToastsFn(prev => [...prev, { id: ++toastId, msg }]);
}
function ToastContainer() {
  const [toasts, setToasts] = useS([]);
  useE(() => {
    setToastsFn = setToasts;
    return () => { setToastsFn = null; };
  }, []);
  useE(() => {
    if (toasts.length === 0) return;
    const t = setTimeout(() => setToasts(prev => prev.slice(1)), 2200);
    return () => clearTimeout(t);
  }, [toasts]);
  return (
    <div className="fixed bottom-24 right-5 z-[150] flex flex-col gap-2 items-end pointer-events-none">
      {toasts.slice(-3).map(t => (
        <div key={t.id} className="bg-[var(--vert)] text-[var(--bg)] px-4 py-2.5 rounded-full font-semibold text-sm shadow-2xl flex items-center gap-2"
             style={{ animation: 'toastIn 0.3s ease' }}>
          <Icon.Check className="w-4 h-4"/>
          {t.msg}
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { showToast });

/* --- Avant l'ouverture : seulement « RIVA arrive bientôt » ---
   Décidé par partage.js (rivaBientot) : la date RESTO.ouverture de carte.js,
   ou l'interrupteur du tableau de bord. Le patron, lui, voit le vrai site :
   appui long de 1,5 s sur le logo, puis le mot de passe du tableau de bord. */
function patronConnecte() {
  try { return localStorage.getItem('bt-admin-ouvert') === '1' && !!getAdminKey(); }
  catch (e) { return false; }
}

function Bientot() {
  const mode = window.rivaModeBientot ? rivaModeBientot() : 'auto';
  const ouverture = window.rivaOuverture ? rivaOuverture() : 0;
  const avecDate = mode === 'auto' && ouverture > Date.now();
  const date = avecDate ? new Date(ouverture).toLocaleDateString('fr-FR', {
    weekday: 'long', day: 'numeric', month: 'long', timeZone: 'Europe/Paris',
  }) : '';
  // « à 11 h 30 », sauf si l'ouverture est à minuit
  const heure = avecDate ? new Date(ouverture).toLocaleTimeString('fr-FR', {
    hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris',
  }).replace(':', ' h ').replace(/^0/, '') : '';
  const aHeure = heure && heure !== '0 h 00' ? ' à ' + heure : '';

  // À l'heure d'ouverture, la page se recharge seule et montre le vrai site.
  useE(() => {
    const reste = ouverture - Date.now();
    if (avecDate && reste < 2 ** 31 - 1) {
      const t = setTimeout(() => location.reload(), reste + 1000);
      return () => clearTimeout(t);
    }
  }, []);

  // Appui long sur le logo : accès du patron, comme sur le vrai site.
  const minuteur = React.useRef(null);
  const debut = () => {
    minuteur.current = setTimeout(async () => {
      try { if (navigator.vibrate) navigator.vibrate(50); } catch (e) {}
      const cle = prompt('Mot de passe du tableau de bord :');
      if (cle === null) return;
      try {
        const r = await fetch('/api/admin/auth', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ password: cle }),
        });
        if (r.ok) {
          setAdminKeyValue(cle);
          localStorage.setItem('bt-admin-ouvert', '1');
          location.reload();
        } else {
          alert('Mot de passe incorrect');
        }
      } catch (e) { alert('Connexion au serveur impossible'); }
    }, 1500);
  };
  const fin = () => { clearTimeout(minuteur.current); minuteur.current = null; };

  return (
    <main className="min-h-[100dvh] flex flex-col items-center justify-center text-center px-6 py-10 sm:py-12 bg-[var(--bg)] text-[var(--cream)]">
      <img src="logo/riva-logo.png" alt="RIVA" draggable="false"
           className="h-56 sm:h-72 lg:h-80 mb-8 sm:mb-10 select-none"
           style={{ WebkitTouchCallout: 'none', maxHeight: '34vh', width: 'auto', maxWidth: '100%' }}
           onPointerDown={debut} onPointerUp={fin} onPointerLeave={fin} onPointerCancel={fin}
           onContextMenu={e => e.preventDefault()}/>
      <p className="font-mono text-xs lg:text-sm tracking-[0.3em] uppercase text-[var(--vert)] mb-4">Bientôt</p>
      <h1 className="font-display text-5xl sm:text-7xl lg:text-8xl mb-6 lg:mb-8">RIVA arrive</h1>
      <p className="text-[var(--cream-2)] text-lg lg:text-xl leading-relaxed max-w-md lg:max-w-xl">
        Pizzas, panuozzos et pâtes, <span className="whitespace-nowrap">100 % halal.</span><br/>
        {avecDate
          ? <>Les commandes ouvrent le <span className="text-[var(--vert-2)] font-semibold whitespace-nowrap">{date}{aHeure}</span>.</>
          : <>Les commandes en ligne ouvrent très bientôt.</>}
      </p>
      <div className="mt-8 sm:mt-10 text-sm lg:text-base text-[var(--muted)] space-y-1">
        <p>{RESTO.adresse}</p>
        {RESTO.instagram && (
          <p><a className="underline hover:text-[var(--vert-2)]" href={`https://instagram.com/${RESTO.instagram}`} target="_blank" rel="noopener">Instagram · @{RESTO.instagram}</a></p>
        )}
      </div>
    </main>
  );
}

// Un client venu par le QR de sa table voit toujours le vrai site.
const aTable = !!(window.getTable && getTable());
const ecranBientot = !!(window.rivaBientot && rivaBientot()) && !patronConnecte() && !aTable;
ReactDOM.createRoot(document.getElementById('app')).render(ecranBientot ? <Bientot/> : <App/>);
