/* ============================================================
   RIVA — Panier, envoi de la commande et tableau de bord
   ============================================================ */

const { useState: useStateC, useEffect: useEffectC, useMemo: useMemoC, useRef: useRefC } = React;

/* ---------- correspondance des statuts ---------- */
const STATUTS = {
  nouvelle:    { css: 'new',       label: 'Nouvelle',       suivant: 'preparation', bouton: 'Confirmer & préparer' },
  preparation: { css: 'preparing', label: 'En préparation', suivant: 'prete',       bouton: 'Marquer prête' },
  prete:       { css: 'ready',     label: 'Prête',          suivant: 'terminee',    bouton: 'Marquer servie' },
  terminee:    { css: 'delivered', label: 'Terminée',       suivant: null,          bouton: null },
  annulee:     { css: 'delivered', label: 'Annulée',        suivant: null,          bouton: null },
};

// ====== PANIER ======
/* Remarques toutes prêtes : un toucher, c'est écrit. */
const REMARQUES_RAPIDES = ['Sans oignons', 'Sans fromage', 'Sans sauce', 'Pas épicé', 'Bien cuit'];

/* La remarque d'un plat dans le panier. Fermée, c'est un petit lien
   « Ajouter une remarque » ; ouverte, un champ et des remarques toutes prêtes. */
function RemarquePlat({ valeur, onChange }) {
  const [ouvert, setOuvert] = useStateC(!!valeur);
  if (!ouvert) {
    return (
      <button onClick={() => setOuvert(true)} className="mt-2 text-xs font-semibold text-[var(--vert)] hover:underline">
        + Ajouter une remarque (sans oignons…)
      </button>
    );
  }
  const basculer = (r) => {
    const parts = (valeur || '').split(',').map(x => x.trim()).filter(Boolean);
    const i = parts.findIndex(p => p.toLowerCase() === r.toLowerCase());
    if (i >= 0) parts.splice(i, 1); else parts.push(r);
    onChange(parts.join(', '));
  };
  return (
    <div className="mt-2">
      <input value={valeur || ''} onChange={(e) => onChange(e.target.value)} maxLength={120}
             placeholder="Votre remarque pour ce plat"
             className="w-full px-3 py-2 text-sm bg-[var(--bg-2,#141310)] border border-[var(--line)] rounded-lg focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
      <div className="flex flex-wrap gap-1.5 mt-1.5">
        {REMARQUES_RAPIDES.map(r => {
          const actif = (valeur || '').toLowerCase().split(',').map(x => x.trim()).includes(r.toLowerCase());
          return (
            <button key={r} onClick={() => basculer(r)}
                    className={`px-2.5 py-1 rounded-full text-[11px] font-semibold border ${actif ? 'bg-[var(--vert)] text-[var(--bg)] border-[var(--vert)]' : 'border-[var(--line)] text-[var(--cream-2)]'}`}>
              {r}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function CartDrawer({ open, onClose, cart, updateQty, removeItem, setRemarque, clearCart, onCheckout, subtotal, table }) {
  useEffectC(() => {
    document.body.style.overflow = open ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);
  return (
    <>
      <div className={`cart-overlay ${open ? 'open' : ''}`} onClick={onClose}/>
      <aside className={`cart-drawer ${open ? 'open' : ''}`}>
        <div className="flex items-center justify-between px-5 py-4 border-b border-[var(--line)]">
          <div>
            <h3 className="font-display text-2xl">Votre commande</h3>
            <div className="text-xs text-[var(--muted)] mt-0.5">
              {table ? `Table ${table}` : `${cart.length} article${cart.length > 1 ? 's' : ''}`}
            </div>
          </div>
          <button onClick={onClose} aria-label="Fermer" className="w-10 h-10 rounded-full bg-[var(--bg)] flex items-center justify-center">
            <Icon.Close className="w-5 h-5"/>
          </button>
        </div>

        <div className="flex-1 overflow-y-auto px-5 py-4">
          {cart.length === 0 ? (
            <div className="h-full flex flex-col items-center justify-center text-center py-10">
              <div className="w-20 h-20 rounded-full bg-[var(--bg)] flex items-center justify-center mb-4">
                <Icon.Bag className="w-9 h-9 text-[var(--muted)]"/>
              </div>
              <h4 className="font-display text-2xl text-[var(--cream)]">Commande vide</h4>
              <p className="text-sm text-[var(--muted)] mt-2 max-w-xs">Ajoutez un plat pour commencer.</p>
              <button onClick={() => {
                  onClose();
                  setTimeout(() => document.getElementById('menu')?.scrollIntoView({ behavior: 'smooth', block: 'start' }), 350);
                }} className="btn btn-primary mt-6">
                Voir la carte <Icon.ArrowRight className="w-4 h-4"/>
              </button>
            </div>
          ) : (
            <ul className="space-y-3">
              {cart.map((it, i) => (
                <li key={i} className="flex gap-3 bg-[var(--bg)] rounded-xl p-3">
                  <PlatVisuel item={it} className="w-16 h-16 rounded-lg shrink-0 overflow-hidden"/>
                  <div className="flex-1 min-w-0">
                    <div className="flex items-start justify-between gap-2">
                      <h5 className="font-display text-base leading-tight">{it.name}</h5>
                      <button onClick={() => removeItem(i)} aria-label={`Retirer ${it.name}`}
                              className="text-[var(--muted)] hover:text-[var(--rouge-2)] shrink-0">
                        <Icon.Trash className="w-4 h-4"/>
                      </button>
                    </div>
                    {it.options && Object.keys(it.options).length > 0 && (
                      <ul className="text-[11px] text-[var(--muted)] mt-1 space-y-0.5">
                        {Object.entries(it.options).map(([k, v]) => (
                          <li key={k}><span className="text-[var(--cream-2)]/70">{k} :</span> {v}</li>
                        ))}
                      </ul>
                    )}
                    <div className="flex items-center justify-between mt-2">
                      <div className="qty">
                        <button onClick={() => updateQty(i, it.qty - 1)} aria-label="Retirer un">−</button>
                        <span className="v">{it.qty}</span>
                        <button onClick={() => updateQty(i, it.qty + 1)} aria-label="Ajouter un">+</button>
                      </div>
                      <div className="font-display text-lg text-[var(--vert)]">{(it.price * it.qty).toFixed(2)}€</div>
                    </div>
                    {setRemarque && <RemarquePlat valeur={it.remarque} onChange={(v) => setRemarque(i, v)}/>}
                  </div>
                </li>
              ))}
            </ul>
          )}
        </div>

        {cart.length > 0 && (
          <div className="px-5 py-4 border-t border-[var(--line)] space-y-3 bg-[var(--bg)]">
            <div className="flex items-center justify-between">
              <span className="text-sm text-[var(--muted)]">Sous-total</span>
              <span className="font-display text-2xl text-[var(--cream)]">{subtotal.toFixed(2)}€</span>
            </div>
            <button onClick={onCheckout} className="w-full btn btn-primary !py-4">
              {table ? `Envoyer en cuisine · table ${table}` : 'Passer commande'} <Icon.ArrowRight className="w-5 h-5"/>
            </button>
            <button onClick={clearCart} className="w-full text-xs text-[var(--muted)] hover:text-[var(--rouge-2)] py-1">
              Tout retirer
            </button>
          </div>
        )}
      </aside>
    </>
  );
}

// ====== ENVOI DE LA COMMANDE ======
function CheckoutModal({ open, onClose, cart, subtotal, clearCart, table }) {
  const livraisonPossible = SHOP.delivery.active !== false;
  const modeParDefaut = table ? 'surplace' : (livraisonPossible ? 'livraison' : 'emporter');

  const [step, setStep] = useStateC(1);          // 1 = mode, 2 = coordonnées, 3 = paiement
  const [mode, setMode] = useStateC(modeParDefaut);
  const [form, setForm] = useStateC({ name: '', phone: '', email: '', address: '', notes: '', pickupTime: '' });
  const [payment, setPayment] = useStateC(null);
  const [confirmed, setConfirmed] = useStateC(false);
  const [commande, setCommande] = useStateC(null);
  const [horsLigne, setHorsLigne] = useStateC(false);
  const [hasSaved, setHasSaved] = useStateC(false);
  const [envoiEnCours, setEnvoiEnCours] = useStateC(false);
  const [erreurEnvoi, setErreurEnvoi] = useStateC(null);

  useEffectC(() => {
    if (!open) return;
    setStep(1); setConfirmed(false); setCommande(null); setPayment(null); setHorsLigne(false);
    setMode(table ? 'surplace' : (livraisonPossible ? 'livraison' : 'emporter'));
    try {
      const saved = JSON.parse(localStorage.getItem('bt-client') || 'null');
      if (saved && saved.name) {
        setForm({ name: saved.name || '', phone: saved.phone || '', email: saved.email || '',
                  address: saved.address || '', notes: '', pickupTime: '' });
        setHasSaved(true);
      } else {
        setForm({ name: '', phone: '', email: '', address: '', notes: '', pickupTime: '' });
        setHasSaved(false);
      }
    } catch (e) { setHasSaved(false); }
  }, [open, table]);

  useEffectC(() => {
    document.body.style.overflow = open ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);

  const oublierInfos = () => {
    try { localStorage.removeItem('bt-client'); } catch (e) {}
    setForm({ name: '', phone: '', email: '', address: '', notes: '', pickupTime: '' });
    setHasSaved(false);
  };

  const fraisLivraison = mode === 'livraison' && subtotal < SHOP.delivery.freeAbove ? SHOP.delivery.fee : 0;
  const total = subtotal + fraisLivraison;
  const minimumAtteint = mode !== 'livraison' || subtotal >= SHOP.delivery.minOrder;

  // Champs obligatoires selon le mode : on ne demande que ce qui sert vraiment.
  // En salle, on ne demande rien du tout : la table est déjà connue, la
  // commande part en cuisine telle quelle.
  const coordonneesCompletes =
    mode === 'surplace'  ? true
  : mode === 'emporter'  ? !!form.name.trim() && !!form.phone.trim()
  : /* livraison */        !!form.name.trim() && !!form.phone.trim() && !!form.address.trim();

  const construireCommande = (pay) => ({
    mode,
    table: mode === 'surplace' ? table : null,
    // Sur place, aucune donnée personnelle ne quitte le téléphone du client :
    // ni nom, ni téléphone, ni email. Le numéro de table identifie la commande.
    client: mode === 'surplace' ? { nom: '', tel: '', email: '', adresse: '' } : {
      nom: form.name.trim(),
      tel: form.phone.trim(),
      email: form.email.trim(),
      adresse: mode === 'livraison' ? form.address.trim() : '',
    },
    heureRetrait: mode === 'emporter' ? (form.pickupTime || '') : '',
    note: form.notes.trim(),
    lignes: cart.map(it => ({
      id: it.id,
      nom: it.name,
      qte: it.qty,
      prixUnitaire: it.price,
      // La remarque part avec le plat et s'imprime en gros sous lui.
      options: (it.options || it.remarque)
        ? { ...(it.options || {}), ...(it.remarque && it.remarque.trim() ? { Remarque: it.remarque.trim() } : {}) }
        : null,
    })),
    sousTotal: subtotal,
    fraisLivraison,
    total,
    // En salle, on ne demande pas non plus comment le client réglera :
    // il paiera au comptoir en partant, comme dans n'importe quel restaurant.
    paiement: {
      methode: mode === 'surplace' ? 'comptoir' : (pay?.method || 'comptoir'),
      paye: mode === 'surplace' ? false : !!pay?.paid,
      dernier4: mode === 'surplace' ? '' : (pay?.last4 || ''),
    },
  });

  const surPaiementReussi = async (pay) => {
    if (envoiEnCours) return;
    setEnvoiEnCours(true);
    setPayment(pay);
    setErreurEnvoi(null);
    const resultat = await envoyerCommande(construireCommande(pay));
    if (!resultat.ok) {
      // Rien n'est parti : on le dit clairement et le panier reste intact.
      setErreurEnvoi(resultat.erreur);
      setEnvoiEnCours(false);
      return;
    }
    setCommande(resultat.commande);
    setHorsLigne(resultat.horsLigne);
    // Rien à mémoriser en salle : il n'y a aucune coordonnée à retenir.
    if (mode !== 'surplace') {
      try {
        localStorage.setItem('bt-client', JSON.stringify({
          name: form.name, phone: form.phone, email: form.email, address: form.address,
        }));
      } catch (e) {}
    }
    setConfirmed(true);
    setEnvoiEnCours(false);
  };

  if (!open) return null;

  const surPlace = mode === 'surplace';
  const nbEtapes = surPlace ? 2 : 3;
  const titreEtape = confirmed ? 'Commande envoyée'
    : step === 1 ? 'Mode de service'
    : step === 2 ? (surPlace ? 'Un mot pour la cuisine ?' : 'Vos coordonnées')
    : 'Règlement';

  return (
    <div className="fixed inset-0 z-[200] flex items-center justify-center p-3 md:p-6 voile-fonce backdrop-blur-sm" onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}
           className="w-full max-w-[640px] max-h-[92vh] bg-[var(--bg-2)] rounded-3xl border border-[var(--line)] flex flex-col overflow-hidden">
        <div className="px-6 py-5 border-b border-[var(--line)] flex items-center justify-between shrink-0">
          <div>
            <div className="kicker">Étape {confirmed ? nbEtapes : step}/{nbEtapes}</div>
            <h3 className="font-display text-3xl mt-1">{titreEtape}</h3>
          </div>
          <button onClick={onClose} aria-label="Fermer" className="w-10 h-10 rounded-full bg-[var(--bg)] flex items-center justify-center">
            <Icon.Close className="w-5 h-5"/>
          </button>
        </div>

        <div className="overflow-y-auto flex-1">
          {!confirmed && erreurEnvoi && (
            <div role="alert" className="mx-6 mt-5 rounded-xl p-4 bg-[var(--rouge)]/15 border border-[var(--rouge)]/40 text-[var(--cream)] text-sm leading-relaxed">
              <strong className="text-[var(--rouge-2)]">Votre commande n'est pas partie.</strong> {erreurEnvoi}
              <span className="block mt-1 text-[var(--cream-2)]">Votre panier est gardé : réessayez dans un instant{SHOP.phone ? `, ou appelez le ${SHOP.phone}` : ''}.</span>
            </div>
          )}
          {confirmed ? (
            <ConfirmedView commande={commande} horsLigne={horsLigne} table={table}
                           onClose={() => { clearCart(); onClose(); }}/>
          ) : step === 3 ? (
            <PaymentForm
              total={total}
              mode={mode}
              customerInfo={form}
              onSuccess={surPaiementReussi}
              onCancel={() => setStep(2)}
            />
          ) : step === 1 ? (
            <div className="p-6 space-y-3">
              {table ? (
                <>
                  <div className="rounded-2xl p-5 border-2 border-[var(--jade)] bg-[var(--jade)]/10 flex items-center gap-4">
                    <div className="w-14 h-14 rounded-full bg-[var(--jade)] text-white flex items-center justify-center font-display text-2xl shrink-0">
                      {table}
                    </div>
                    <div className="flex-1">
                      <div className="font-display text-3xl">Sur place · table {table}</div>
                      <div className="text-sm text-[var(--cream-2)] mt-1">
                        La commande part directement en cuisine. Le ticket indiquera votre numéro de table, on vous sert à votre place.
                      </div>
                    </div>
                  </div>
                  <button onClick={() => { quitterLaTable(); setMode(livraisonPossible ? 'livraison' : 'emporter'); }}
                          className="text-xs text-[var(--muted)] hover:text-[var(--cream)] underline">
                    Je ne suis pas à cette table, je veux commander à emporter
                  </button>
                </>
              ) : (
                <>
                  <ModeOption
                    selected={mode === 'emporter'}
                    onClick={() => setMode('emporter')}
                    icon={Icon.Bag}
                    title="À emporter"
                    sub={`${SHOP.pickup.time} · sans frais · ${SHOP.address.split(',')[0]}`}
                  />
                  {livraisonPossible && (
                    <ModeOption
                      selected={mode === 'livraison'}
                      onClick={() => setMode('livraison')}
                      icon={Icon.Truck}
                      title="Livraison"
                      sub={`${SHOP.delivery.time} · ${SHOP.delivery.fee.toFixed(2)}€ (offerts dès ${SHOP.delivery.freeAbove}€) · min ${SHOP.delivery.minOrder}€`}
                    />
                  )}
                  <div className="flex items-start gap-3 bg-[var(--bg)] rounded-xl p-3 text-xs text-[var(--cream-2)] mt-1">
                    <Icon.Store className="w-5 h-5 text-[var(--jade)] shrink-0"/>
                    <div>Vous êtes déjà installé dans la salle ? Scannez le QR code posé sur votre table : votre numéro de table partira avec la commande.</div>
                  </div>
                </>
              )}

              {!minimumAtteint && mode === 'livraison' && (
                <div className="bg-[var(--rouge)]/15 border border-[var(--rouge)]/30 text-[var(--rouge-2)] rounded-xl p-3 text-sm">
                  Minimum {SHOP.delivery.minOrder}€ pour la livraison. Il manque {(SHOP.delivery.minOrder - subtotal).toFixed(2)}€.
                </div>
              )}

              <div className="pt-4 mt-4 border-t border-[var(--line)]">
                <div className="text-[10px] uppercase tracking-wider text-[var(--muted)] font-bold mb-3">Récapitulatif</div>
                <ul className="space-y-1.5 text-sm text-[var(--cream-2)]">
                  {cart.map((it, i) => (
                    <li key={i}>
                      <div className="flex justify-between gap-3">
                        <span>{it.qty}× {it.name}</span>
                        <span className="text-[var(--muted)] shrink-0">{(it.price * it.qty).toFixed(2)}€</span>
                      </div>
                      {it.options && (
                        <div className="text-[11px] text-[var(--muted)] pl-4">
                          {Object.entries(it.options).map(([k, v]) => `${k} : ${v}`).join(' · ')}
                        </div>
                      )}
                    </li>
                  ))}
                </ul>
                <div className="mt-3 pt-3 border-t border-[var(--line)] space-y-1 text-sm">
                  <div className="flex justify-between"><span>Sous-total</span><span>{subtotal.toFixed(2)}€</span></div>
                  {mode === 'livraison' && (
                    <div className="flex justify-between">
                      <span>Livraison</span>
                      <span>{fraisLivraison === 0 ? <span className="text-[var(--jade)]">Offerte</span> : `${fraisLivraison.toFixed(2)}€`}</span>
                    </div>
                  )}
                  <div className="flex justify-between text-base font-bold pt-1">
                    <span>Total</span>
                    <span className="font-display text-2xl text-[var(--vert)]">{total.toFixed(2)}€</span>
                  </div>
                </div>
              </div>
            </div>
          ) : (
            <div className="p-6 space-y-4">
              {surPlace && (
                <div className="flex items-start gap-3 bg-[var(--jade)]/10 border border-[var(--jade)]/30 rounded-xl p-4">
                  <Icon.Store className="w-6 h-6 text-[var(--jade)] shrink-0"/>
                  <div className="text-sm text-[var(--cream-2)]">
                    <div className="font-semibold text-[var(--cream)]">Table {table} — rien d'autre à remplir.</div>
                    On ne vous demande ni nom, ni téléphone, ni comment vous réglez : la commande part
                    directement en cuisine, et vous payez au comptoir en partant.
                  </div>
                </div>
              )}

              {!surPlace && hasSaved && (
                <div className="flex items-center gap-3 bg-[var(--vert)]/10 border border-[var(--vert)]/30 rounded-xl p-3">
                  <Icon.Sparkles className="w-5 h-5 text-[var(--vert)] shrink-0"/>
                  <div className="flex-1 text-sm">
                    <div className="font-semibold text-[var(--vert)]">Re-bonjour {form.name?.split(' ')[0] || ''} !</div>
                    <div className="text-xs text-[var(--cream-2)] mt-0.5">Vos infos sont pré-remplies. Modifiez ce qui a changé.</div>
                  </div>
                  <button onClick={oublierInfos} className="text-xs text-[var(--muted)] hover:text-[var(--rouge-2)] underline whitespace-nowrap">
                    Pas moi
                  </button>
                </div>
              )}

              {!surPlace && (
                <Field label="Prénom & nom" required>
                  <input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })}
                         placeholder="Sarah Mansouri"
                         className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
                </Field>
              )}

              {!surPlace && (
                <Field label="Téléphone" required hint="Pour vous joindre en cas de souci sur la commande">
                  <input type="tel" value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })}
                         placeholder="06 12 34 56 78"
                         className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
                </Field>
              )}

              {mode === 'livraison' && (
                <Field label="Adresse de livraison" required>
                  <input value={form.address} onChange={(e) => setForm({ ...form, address: e.target.value })}
                         placeholder="12 rue Villars, 59220 Denain, 3e étage"
                         className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
                </Field>
              )}

              {mode === 'emporter' && (
                <Field label="Heure de retrait" hint={`Préparation environ ${SHOP.pickup.time}`}>
                  <select value={form.pickupTime} onChange={(e) => setForm({ ...form, pickupTime: e.target.value })}
                          className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]">
                    <option value="">Dès que c'est prêt (~20 min)</option>
                    {generateTimeSlots().map(t => <option key={t} value={t}>{t}</option>)}
                  </select>
                </Field>
              )}

              {!surPlace && (
                <Field label="Email" optional hint="Pour recevoir le récapitulatif de la commande">
                  <input type="email" value={form.email} onChange={(e) => setForm({ ...form, email: e.target.value })}
                         placeholder="sarah@email.com"
                         className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
                </Field>
              )}

              <Field label="Une remarque pour la cuisine ?" optional hint="Allergie, plat à adapter… (les remarques par plat se mettent dans le panier)">
                <textarea value={form.notes} onChange={(e) => setForm({ ...form, notes: e.target.value })}
                          rows="2" placeholder="Ex : allergie aux fruits à coque, sans coriandre"
                          className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none resize-none text-[var(--cream)]"/>
              </Field>

              <div className="bg-[var(--bg)] rounded-xl p-3 flex items-center gap-3 mt-2">
                <Icon.Printer className="w-6 h-6 text-[var(--jade)] shrink-0"/>
                <div className="text-xs text-[var(--cream-2)]">
                  Dès validation, le ticket cuisine sort en caisse avec la mention
                  {' '}<strong className="text-[var(--cream)]">{MODES[mode].ticket}{mode === 'surplace' && table ? ` — TABLE ${table}` : ''}</strong>
                  {surPlace ? ' — sans les prix, et sans rien de personnel.' : '.'}
                </div>
              </div>
            </div>
          )}
        </div>

        {!confirmed && step !== 3 && (
          <div className="px-6 py-4 border-t border-[var(--line)] flex items-center justify-between gap-3 bg-[var(--bg)]/50 shrink-0">
            {step === 1 ? (
              <>
                <button onClick={onClose} className="btn btn-ghost !py-3 !px-5">Retour</button>
                <button onClick={() => setStep(2)} disabled={!minimumAtteint}
                        className="btn btn-primary !py-3 !px-6 disabled:opacity-40 disabled:cursor-not-allowed">
                  Continuer <Icon.ArrowRight className="w-4 h-4"/>
                </button>
              </>
            ) : (
              <>
                <button onClick={() => setStep(1)} className="btn btn-ghost !py-3 !px-5">← Retour</button>
                <button
                  onClick={() => surPlace
                    ? surPaiementReussi({ method: 'comptoir', paid: false })
                    : setStep(3)}
                  disabled={!coordonneesCompletes || envoiEnCours}
                  className="btn btn-primary !py-3 !px-6 disabled:opacity-40 disabled:cursor-not-allowed">
                  {surPlace ? (envoiEnCours ? 'Envoi…' : 'Envoyer en cuisine') : 'Continuer vers le règlement'}
                  <Icon.ArrowRight className="w-4 h-4"/>
                </button>
              </>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function generateTimeSlots() {
  const slots = [];
  const now = new Date();
  const start = new Date(now.getTime() + 20 * 60000);
  start.setMinutes(Math.ceil(start.getMinutes() / 15) * 15);
  for (let i = 0; i < 10; i++) {
    const t = new Date(start.getTime() + i * 15 * 60000);
    slots.push(`${String(t.getHours()).padStart(2, '0')}h${String(t.getMinutes()).padStart(2, '0')}`);
  }
  return slots;
}

function ModeOption({ selected, onClick, icon: I, title, sub }) {
  return (
    <button onClick={onClick}
            className={`w-full text-left rounded-2xl p-4 border-2 transition-all flex items-center gap-4
              ${selected ? 'border-[var(--vert)] bg-[var(--vert)]/10' : 'border-[var(--line)] hover:border-[var(--cream)]/30'}`}>
      <div className={`w-12 h-12 rounded-full flex items-center justify-center shrink-0 ${selected ? 'bg-[var(--vert)] text-[var(--bg)]' : 'bg-[var(--bg)] text-[var(--cream)]'}`}>
        <I className="w-5 h-5"/>
      </div>
      <div className="flex-1">
        <div className="font-display text-2xl">{title}</div>
        <div className="text-xs text-[var(--muted)] mt-0.5">{sub}</div>
      </div>
      <div className={`w-5 h-5 rounded-full border-2 shrink-0 ${selected ? 'border-[var(--vert)] bg-[var(--vert)]' : 'border-[var(--line)]'} flex items-center justify-center`}>
        {selected && <div className="w-2 h-2 rounded-full bg-[var(--bg)]"/>}
      </div>
    </button>
  );
}

function Field({ label, required, optional, hint, children }) {
  return (
    <label className="block">
      <div className="text-xs font-bold uppercase tracking-wider text-[var(--cream-2)] mb-1.5 flex items-center justify-between">
        <span>{label} {required && <span className="text-[var(--rouge-2)]">*</span>}</span>
        {optional && <span className="text-[var(--muted)] normal-case font-normal text-[10px]">facultatif</span>}
      </div>
      {children}
      {hint && <div className="text-[11px] text-[var(--muted)] mt-1.5">{hint}</div>}
    </label>
  );
}

function ConfirmedView({ commande, horsLigne, table, onClose }) {
  if (!commande) return null;
  const mode = MODES[commande.mode] || MODES.emporter;
  return (
    <div className="p-8 text-center">
      <div className="w-20 h-20 rounded-full bg-[var(--jade)]/15 border-2 border-[var(--jade)] mx-auto flex items-center justify-center mb-5">
        <Icon.Check className="w-10 h-10 text-[var(--jade)]"/>
      </div>
      <div className="font-hand text-[var(--vert)] text-2xl">{commande.attenteAppel ? 'Presque fini !' : 'Et voilà !'}</div>
      <h3 className="font-display text-4xl mt-1">
        {commande.mode === 'surplace' ? 'C\'est parti en cuisine' : commande.attenteAppel ? 'Appelez-nous pour confirmer' : 'Commande envoyée'}
      </h3>
      {commande.attenteAppel && (
        <div className="mt-4 max-w-sm mx-auto rounded-2xl p-4 border-2 border-[var(--vert)] bg-[var(--vert)]/10 text-left">
          <p className="text-sm text-[var(--cream)] leading-relaxed">
            Nous avons bien reçu la commande <strong>{commande.numero}</strong>. Pour la confirmer,
            <strong> appelez-nous maintenant</strong>. <strong className="text-[var(--rouge-2)]">Sans appel, elle ne sera pas préparée.</strong>
          </p>
          {SHOP.phone && (
            <a href={`tel:${(RESTO.tel || '').replace(/\s/g, '')}`} className="btn btn-primary w-full justify-center mt-3 !py-3">
              <Icon.Phone className="w-4 h-4"/> Appeler le <span className="whitespace-nowrap">{SHOP.phone}</span>
            </a>
          )}
        </div>
      )}
      <p className="text-[var(--cream-2)] mt-3 max-w-sm mx-auto">
        {commande.attenteAppel
          ? 'Donnez votre numéro de commande au téléphone : on lance la préparation dès votre appel.'
          : commande.mode === 'surplace'
          ? `Le ticket vient de sortir en caisse avec la mention SUR PLACE — TABLE ${commande.table}. On vous apporte tout ça.`
          : commande.mode === 'emporter'
            ? 'Le ticket est sorti en caisse avec la mention À EMPORTER. Présentez votre numéro au comptoir.'
            : 'Le ticket est sorti en caisse avec la mention LIVRAISON. On part dès que c\'est prêt.'}
      </p>

      <div className="mt-6 bg-[var(--bg)] rounded-2xl p-5 text-left max-w-sm mx-auto">
        <div className="flex justify-between items-center pb-3 border-b border-[var(--line)]">
          <div>
            <div className="text-[10px] uppercase tracking-wider text-[var(--muted)] font-bold">N° de commande</div>
            <div className="font-display text-2xl text-[var(--vert)]">{commande.numero}</div>
          </div>
          <span className={`mode-chip ${commande.mode}`}>
            {mode.ticket}{commande.table ? ` · ${commande.table}` : ''}
          </span>
        </div>
        <div className="mt-3 space-y-2 text-sm">
          {commande.mode === 'surplace' && <Row label="Table" value={commande.table}/>}
          {commande.mode === 'emporter' && <Row label="Retrait" value={commande.heureRetrait || 'dès que prêt'}/>}
          {commande.mode === 'livraison' && <Row label="Adresse" value={commande.client?.adresse}/>}
          {commande.mode !== 'surplace' && <Row label="Client" value={commande.client?.nom}/>}
          <Row label="Paiement" value={commande.paiement?.paye
            ? <span className="text-[var(--jade)] font-semibold">✓ Réglé</span>
            : <span className="text-[var(--vert)] font-semibold">{commande.paiement?.methode === 'especes' ? 'En espèces' : 'À régler'} {commande.mode === 'livraison' ? 'à la livraison' : 'au retrait'}</span>}/>
          <Row label="Total" value={<span className="font-display text-lg text-[var(--vert)]">{Number(commande.total).toFixed(2)}€</span>}/>
        </div>
      </div>

      {horsLigne && (
        <div className="mt-5 max-w-sm mx-auto bg-[var(--rouge)]/12 border border-[var(--rouge)]/30 text-[var(--rouge-2)] rounded-xl p-3 text-xs leading-relaxed text-left">
          <strong>La caisse n'a pas répondu.</strong> La commande est gardée sur cet appareil mais elle n'est
          pas arrivée en cuisine. Prévenez le personnel, ou appelez le {SHOP.phone}.
        </div>
      )}

      {/* La demande d'avis Google, juste après la commande : c'est le moment
          où le client a son téléphone en main et où il est encore à table. */}
      <DemandeAvis mode={commande.mode} horsLigne={horsLigne}/>

      <button onClick={onClose} className="btn btn-ghost mt-6">
        Continuer <Icon.ArrowRight className="w-4 h-4"/>
      </button>
    </div>
  );
}

/* ====== L'AVIS GOOGLE, À LA FIN DE LA COMMANDE ======
   On propose le lien à tout le monde, sans filtrer sur la note : trier les
   clients selon ce qu'ils vont écrire est interdit par Google et peut faire
   sauter la fiche du restaurant. Les étoiles ici ne servent qu'à ouvrir la
   page d'avis, la vraie note est donnée chez Google. */
function DemandeAvis({ mode, horsLigne }) {
  const [survol, setSurvol] = useStateC(0);
  const [parti, setParti] = useStateC(false);

  // Pas d'avis si la commande n'est pas arrivée en cuisine, ni si le patron
  // a coupé la demande, ni si ce client en a déjà laissé un récemment.
  if (horsLigne || SHOP.demanderAvis === false || avisDejaDemande()) return null;

  const ouvrir = (note) => {
    marquerAvisDemande();
    setParti(true);
    try { window.open(lienAvisGoogle(), '_blank', 'noopener,noreferrer'); } catch (e) {}
  };

  if (parti) {
    return (
      <div className="mt-7 max-w-sm mx-auto rounded-2xl border border-[var(--jade)]/40 bg-[var(--jade)]/10 p-5">
        <div className="font-hand text-[var(--vert)] text-2xl">Merci beaucoup</div>
        <p className="text-sm text-[var(--cream-2)] mt-1">
          La page Google s'est ouverte dans un autre onglet. Ça compte énormément pour un
          restaurant de quartier.
        </p>
      </div>
    );
  }

  return (
    <div className="mt-7 max-w-sm mx-auto rounded-2xl border-2 border-[var(--vert)]/30 bg-[var(--bg)] p-5">
      <div className="font-hand text-[var(--vert)] text-2xl leading-none">Un petit coup de pouce ?</div>
      <h4 className="font-display text-2xl mt-1">Donnez-nous votre avis</h4>
      <p className="text-sm text-[var(--cream-2)] mt-2">
        {mode === 'surplace'
          ? "Vous êtes encore à table, c'est le bon moment : votre avis Google aide vraiment la maison."
          : 'Un avis Google, ça prend trente secondes et ça aide vraiment la maison.'}
      </p>

      {/* Les étoiles ouvrent la page d'avis Google, quelle que soit celle choisie */}
      <div className="flex justify-center gap-1.5 mt-4" onMouseLeave={() => setSurvol(0)}>
        {[1, 2, 3, 4, 5].map(n => (
          <button key={n}
                  onClick={() => ouvrir(n)}
                  onMouseEnter={() => setSurvol(n)}
                  aria-label={`Donner ${n} étoile${n > 1 ? 's' : ''} sur Google`}
                  className="p-1 transition-transform hover:scale-110">
            <Icon.Star className={`w-8 h-8 ${n <= survol ? 'text-[var(--vert)]' : 'text-[var(--line)]'}`}/>
          </button>
        ))}
      </div>

      <button onClick={() => ouvrir(0)} className="btn btn-primary w-full mt-4 !py-3">
        <GoogleG className="w-4 h-4"/> Laisser un avis Google
      </button>
      <div className="text-[10px] text-[var(--muted)] mt-2">
        Ça ouvre Google dans un autre onglet. Votre commande est déjà partie en cuisine.
      </div>
    </div>
  );
}

/* Le « G » de Google, à ses couleurs officielles. */
function GoogleG({ className }) {
  return (
    <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
      <path fill="#4285F4" d="M12.18 11.78v3.41h4.74c-.21 1.18-.84 2.18-1.78 2.86l2.88 2.23c1.68-1.55 2.65-3.84 2.65-6.56 0-.63-.06-1.24-.16-1.83l-8.33-.11z"/>
      <path fill="#34A853" d="M5.62 13.31l-.65.5-2.3 1.79c1.46 2.9 4.45 4.9 7.94 4.9 2.4 0 4.42-.79 5.9-2.15l-2.88-2.23c-.79.53-1.81.85-3.02.85-2.32 0-4.29-1.57-4.99-3.66z"/>
      <path fill="#FBBC04" d="M2.67 8.4C2.24 9.51 2 10.72 2 12s.24 2.49.67 3.6c.96-.74 3.41-2.65 3.41-2.65-.13-.39-.21-.81-.21-1.25 0-.44.08-.86.21-1.25 0 0-2.45-1.91-3.41-2.65z"/>
      <path fill="#EA4335" d="M12.18 6.84c1.31 0 2.48.45 3.41 1.33l2.55-2.55C16.6 4.13 14.58 3.4 12.18 3.4c-3.49 0-6.48 2-7.94 4.9l3.41 2.65c.7-2.09 2.67-3.66 4.99-3.66z"/>
    </svg>
  );
}

function Row({ label, value }) {
  return (
    <div className="flex justify-between gap-3">
      <span className="text-[var(--muted)]">{label}</span>
      <span className="text-right">{value}</span>
    </div>
  );
}

/* ============================================================
   TABLEAU DE BORD (vue patron depuis le site)
   Les commandes viennent du serveur de caisse, en direct.
   ============================================================ */

function AdminView({ onClose, onLock, onMenuChange }) {
  const [commandes, setCommandes] = useStateC([]);
  const [filtre, setFiltre] = useStateC('toutes');
  const [connecte, setConnecte] = useStateC(false);

  /* Les réglages du tableau de bord partent au serveur pour que les clients
     les voient. S'il les refuse (mot de passe différent de celui du
     restaurant), on le dit : sinon le patron croirait avoir enregistré. */
  useEffectC(() => {
    if (window.partagerTout) partagerTout();
    const refus = (e) => {
      const statut = e.detail && e.detail.statut;
      showToast(statut === 0
        ? 'Serveur injoignable : ce changement ne se voit que sur cet appareil.'
        : 'Changement refusé par le restaurant : mot de passe du tableau de bord différent.');
    };
    window.addEventListener('riva-reglage-refuse', refus);
    return () => window.removeEventListener('riva-reglage-refuse', refus);
  }, []);

  // Chargement initial puis mise à jour en direct
  useEffectC(() => {
    let flux = null;
    let annule = false;

    const charger = async () => {
      try {
        const rep = await fetch(urlServeur('/api/commandes'));
        const data = await rep.json();
        if (!annule) { setCommandes(data.commandes || []); setConnecte(true); }
      } catch (e) {
        if (!annule) {
          setConnecte(false);
          try { setCommandes(JSON.parse(localStorage.getItem('bt-commandes') || '[]')); } catch (e2) {}
        }
      }
    };
    charger();

    try {
      flux = new EventSource(urlServeur('/api/flux'));
      flux.onopen = () => setConnecte(true);
      flux.onerror = () => setConnecte(false);
      flux.addEventListener('commande', (ev) => {
        const c = JSON.parse(ev.data);
        setCommandes(prev => [c, ...prev.filter(x => x.numero !== c.numero)]);
      });
      flux.addEventListener('statut', (ev) => {
        const c = JSON.parse(ev.data);
        setCommandes(prev => prev.map(x => x.numero === c.numero ? c : x));
      });
    } catch (e) {}

    return () => { annule = true; if (flux) flux.close(); };
  }, []);

  const avancer = async (commande) => {
    const suivant = STATUTS[commande.statut]?.suivant;
    if (!suivant) return;
    const qrAValider = commande.mode === 'surplace' && commande.origine === 'qr' && commande.statut === 'nouvelle';
    const appelAValider = !!commande.attenteAppel && commande.statut === 'nouvelle';
    if (appelAValider && !window.confirm(`Le client ${commande.client?.nom || ''} a-t-il bien appelé pour confirmer ? Le ticket cuisine va sortir à la caisse.`)) return;
    if (qrAValider && !window.confirm(`As-tu vérifié que la table ${commande.table || '?'} est bien occupée ? Le ticket cuisine va sortir à la caisse.`)) return;
    setCommandes(prev => prev.map(c => c.numero === commande.numero ? { ...c, statut: suivant } : c));
    try {
      const response = await fetch(urlServeur('/api/commandes/' + encodeURIComponent(commande.numero) + '/statut'), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ statut: suivant }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok) throw new Error(data.erreur || 'mise à jour refusée');
      setCommandes(prev => prev.map(c => c.numero === commande.numero ? data.commande : c));
      // Le ticket cuisine ne sort pas ici (ce peut être un téléphone) : la
      // caisse reçoit la validation et l'imprime sur l'imprimante à tickets.
      if (qrAValider) showToast(`Table ${commande.table || '?'} validée : le ticket cuisine sort à la caisse.`);
      if (appelAValider) showToast(`Commande ${commande.numero} confirmée : le ticket cuisine sort à la caisse.`);
    } catch (e) {
      setCommandes(prev => prev.map(c => c.numero === commande.numero ? commande : c));
      showToast('Impossible de mettre à jour cette commande.');
    }
  };

  const annuler = async (commande) => {
    const qr = commande.mode === 'surplace' && commande.origine === 'qr';
    const question = qr
      ? `La table ${commande.table || '?'} est-elle bien occupée ? Annuler cette commande QR ? Elle disparaîtra de la file active et restera dans l'historique.`
      : `Annuler la commande ${commande.numero} ? Elle disparaîtra de la file active et restera dans l'historique.`;
    if (!window.confirm(question)) return;
    try {
      const response = await fetch(urlServeur('/api/commandes/' + encodeURIComponent(commande.numero) + '/statut'), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ statut: 'annulee', motif: qr ? 'Table non confirmée sur place' : 'Annulée par le personnel' }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok) throw new Error(data.erreur || 'annulation refusée');
      setCommandes(prev => prev.map(c => c.numero === commande.numero ? data.commande : c));
    } catch (e) {
      showToast('Impossible d’annuler cette commande.');
    }
  };

  const filtrees = filtre === 'toutes' ? commandes : commandes.filter(c => c.statut === filtre);
  const compte = (s) => commandes.filter(c => c.statut === s).length;
  const chiffre = commandes.reduce((s, c) => s + (c.statut === 'annulee' ? 0 : Number(c.total || 0)), 0);

  return (
    <div className="min-h-screen bg-[var(--bg)] pt-24 pb-20">
      <div className="max-w-[1400px] mx-auto px-5 md:px-8">
        <div className="flex items-end justify-between gap-4 mb-8 flex-wrap">
          <div>
            <div className="kicker mb-3">Vue patron · Tableau de bord</div>
            <h1 className="font-display text-5xl md:text-6xl">Commandes en direct</h1>
            <p className="text-[var(--muted)] mt-2 text-sm max-w-xl">
              Sur place, à emporter ou en livraison : tout arrive ici. Pour l'écran de cuisine
              en plein écran avec impression automatique, ouvrez la page Caisse.
            </p>
          </div>
          <div className="flex flex-wrap gap-2 items-center">
            <span className={`admin-status ${connecte ? 'ready' : 'delivered'}`}>
              <span className={`w-1.5 h-1.5 rounded-full bg-current ${connecte ? 'pulse-dot' : ''}`}/>
              {connecte ? 'Caisse connectée' : 'Caisse injoignable'}
            </span>
            <a href="../caisse/caisse.html" target="_blank" rel="noopener" className="btn btn-primary !py-2 !px-4 !text-xs">
              <Icon.Printer className="w-4 h-4"/> Ouvrir la caisse
            </a>
            <button onClick={onClose} className="btn btn-ghost !py-2 !px-4 !text-xs">← Site</button>
            {onLock && (
              <button onClick={onLock} title="Se déconnecter du tableau de bord" className="btn btn-ghost !py-2 !px-3 !text-xs">
                <Icon.Lock className="w-3.5 h-3.5"/>
              </button>
            )}
          </div>
        </div>

        <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
          <StatCard label="Nouvelles" value={compte('nouvelle')} accent="or" sub="à confirmer"/>
          <StatCard label="En préparation" value={compte('preparation')} accent="orange" sub="en cuisine"/>
          <StatCard label="Prêtes" value={compte('prete')} accent="jade" sub="à servir"/>
          <StatCard label="Total encaissable" value={`${chiffre.toFixed(0)}€`} accent="cream" sub={`${commandes.length} commandes`}/>
        </div>

        <div className="flex gap-2 mb-5 overflow-x-auto no-scrollbar pb-2">
          {[
            { id: 'toutes', label: `Toutes (${commandes.length})` },
            { id: 'nouvelle', label: `Nouvelles (${compte('nouvelle')})` },
            { id: 'preparation', label: `En préparation (${compte('preparation')})` },
            { id: 'prete', label: `Prêtes (${compte('prete')})` },
            { id: 'terminee', label: 'Terminées' },
            { id: 'annulee', label: `Annulées (${compte('annulee')})` },
          ].map(f => (
            <button key={f.id} onClick={() => setFiltre(f.id)}
                    className={`px-4 py-2 rounded-full whitespace-nowrap text-sm font-semibold transition-colors shrink-0
                      ${filtre === f.id ? 'bg-[var(--vert)] text-[var(--bg)]' : 'bg-[var(--bg-2)] text-[var(--muted)] hover:text-[var(--cream)]'}`}>
              {f.label}
            </button>
          ))}
        </div>

        <div className="grid lg:grid-cols-2 gap-4">
          {filtrees.map(c => (
            <OrderCard key={c.numero} commande={c} onAdvance={() => avancer(c)} onCancel={() => annuler(c)}/>
          ))}
          {filtrees.length === 0 && (
            <div className="lg:col-span-2 py-16 text-center text-[var(--muted)]">
              Aucune commande dans cet état pour l'instant.
            </div>
          )}
        </div>

        <MenuManager onChange={onMenuChange}/>
        <AdminSettings/>
      </div>
    </div>
  );
}

/* L'écran « RIVA arrive bientôt » : ce que voient les clients.
   Automatique = suit la date d'ouverture écrite dans carte.js. */
function InterrupteurBientot() {
  const [mode, setMode] = useStateC(() => (window.rivaModeBientot ? rivaModeBientot() : 'auto'));
  const [occupe, setOccupe] = useStateC(false);
  const ouverture = window.rivaOuverture ? rivaOuverture() : 0;
  const fermeMaintenant = mode === 'oui' || (mode === 'auto' && Date.now() < ouverture);
  const dateAuto = ouverture
    ? new Date(ouverture).toLocaleString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })
    : '';

  const choisir = async (valeur) => {
    setOccupe(true);
    const ok = window.reglerBientot ? await reglerBientot(valeur) : false;
    setOccupe(false);
    if (ok) {
      setMode(valeur || 'auto');
      showToast(valeur === 'oui' ? 'Les clients voient « RIVA arrive bientôt »'
              : valeur === 'non' ? 'Site ouvert : les clients peuvent commander'
              : 'Retour à la date automatique');
    } else {
      showToast('Le serveur a refusé : reconnectez-vous au tableau de bord');
    }
  };

  const bouton = (actif) => `btn !py-3 !px-5 ${actif ? 'btn-primary' : 'btn-ghost'}`;

  return (
    <div className="admin-card mb-4">
      <div className="flex items-center gap-3 mb-4">
        <div className={`w-3 h-3 rounded-full ${fermeMaintenant ? 'bg-[var(--rouge-2)]' : 'bg-[var(--vert)]'}`}/>
        <div>
          <div className="font-semibold">
            {fermeMaintenant ? 'Écran « RIVA arrive bientôt » affiché' : 'Site ouvert aux commandes'}
          </div>
          <div className="text-xs text-[var(--muted)] mt-0.5">
            {mode === 'auto'
              ? (dateAuto ? `Automatique : ouverture le ${dateAuto}` : "Automatique : pas de date d’ouverture")
              : 'Choisi à la main'}
          </div>
        </div>
      </div>
      <div className="flex flex-wrap gap-2">
        <button disabled={occupe} onClick={() => choisir('oui')} className={bouton(mode === 'oui')}>Afficher « Bientôt »</button>
        <button disabled={occupe} onClick={() => choisir('non')} className={bouton(mode === 'non')}>Ouvrir le site</button>
        <button disabled={occupe} onClick={() => choisir(null)} className={bouton(mode === 'auto')}>Automatique (date)</button>
      </div>
    </div>
  );
}

function AdminSettings() {
  const [open, setOpen] = useStateC(false);
  const [current, setCurrent] = useStateC('');
  const [newKey, setNewKey] = useStateC('');
  const [confirm, setConfirm] = useStateC('');
  const [msg, setMsg] = useStateC(null);

  const submit = async (e) => {
    e.preventDefault();
    setMsg(null);
    if (current !== getAdminKey()) {
      setMsg({ type: 'error', text: 'Le mot de passe actuel est incorrect.' });
      return;
    }
    if (newKey.length < 12) {
      setMsg({ type: 'error', text: 'Le nouveau mot de passe doit faire au moins 12 caractères.' });
      return;
    }
    if (newKey !== confirm) {
      setMsg({ type: 'error', text: 'La confirmation ne correspond pas.' });
      return;
    }
    const accepte = window.partagerCleAdmin ? await partagerCleAdmin(current, newKey) : true;
    if (!accepte) {
      setMsg({ type: 'error', text: 'Le restaurant a refusé : le mot de passe actuel ne correspond pas à celui du serveur.' });
      return;
    }
    setAdminKeyValue(newKey);
    setMsg({ type: 'success', text: 'Mot de passe mis à jour. Notez-le quelque part.' });
    setCurrent(''); setNewKey(''); setConfirm('');
    setTimeout(() => setMsg(null), 4000);
  };

  return (
    <div className="mt-12 max-w-2xl">
      <h2 className="font-display text-3xl mb-2">Paramètres</h2>
      <p className="text-[var(--muted)] text-sm mb-5">L'ouverture du site aux clients et l'accès au tableau de bord.</p>

      <InterrupteurBientot/>

      <div className="admin-card">
        <button onClick={() => setOpen(!open)} className="w-full flex items-center justify-between text-left">
          <div className="flex items-center gap-3">
            <div className="w-10 h-10 rounded-full bg-[var(--vert)]/15 flex items-center justify-center">
              <Icon.Lock className="w-4 h-4 text-[var(--vert)]"/>
            </div>
            <div>
              <div className="font-semibold">Changer le mot de passe</div>
              <div className="text-xs text-[var(--muted)] mt-0.5">Le code qui débloque cette vue depuis le site</div>
            </div>
          </div>
          <svg viewBox="0 0 24 24" className={`w-5 h-5 text-[var(--muted)] transition-transform ${open ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" strokeWidth="2">
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </button>

        {open && (
          <form onSubmit={submit} className="mt-5 pt-5 border-t border-[var(--line)] space-y-4">
            <div>
              <label className="text-xs font-bold uppercase tracking-wider text-[var(--cream-2)] mb-1.5 block">Mot de passe actuel</label>
              <input type="password" value={current} onChange={e => setCurrent(e.target.value)} required placeholder="••••••••"
                     className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)]"/>
            </div>
            <div>
              <label className="text-xs font-bold uppercase tracking-wider text-[var(--cream-2)] mb-1.5 block">Nouveau mot de passe</label>
              <input type="password" value={newKey} onChange={e => setNewKey(e.target.value)} required minLength="12" placeholder="12 caractères minimum"
                     className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)] font-mono"/>
              <div className="text-[11px] text-[var(--muted)] mt-1.5">Minimum 12 caractères. Il est enregistré sur le serveur et conservé en session dans ce navigateur.</div>
            </div>
            <div>
              <label className="text-xs font-bold uppercase tracking-wider text-[var(--cream-2)] mb-1.5 block">Confirmez</label>
              <input type="password" value={confirm} onChange={e => setConfirm(e.target.value)} required minLength="12" placeholder="Retapez le même"
                     className="w-full px-4 py-3 bg-[var(--bg)] border border-[var(--line)] rounded-xl focus:border-[var(--vert)] outline-none text-[var(--cream)] font-mono"/>
            </div>

            {msg && (
              <div className={`rounded-xl p-3 text-sm ${msg.type === 'success'
                  ? 'bg-[var(--jade)]/15 text-[var(--jade)] border border-[var(--jade)]/30'
                  : 'bg-[var(--rouge)]/15 text-[var(--rouge-2)] border border-[var(--rouge)]/30'}`}>
                {msg.text}
              </div>
            )}

            <div className="flex gap-2">
              <button type="button" onClick={() => { setOpen(false); setMsg(null); }} className="btn btn-ghost !py-3 !px-5">Annuler</button>
              <button type="submit" className="btn btn-primary !py-3 !px-6 flex-1">Enregistrer</button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

function StatCard({ label, value, accent, sub }) {
  const colors = {
    or: 'text-[var(--vert)]',
    orange: 'text-[var(--rouge)]',
    jade: 'text-[var(--jade)]',
    cream: 'text-[var(--cream)]',
  };
  return (
    <div className="admin-card">
      <div className="text-[11px] uppercase tracking-wider text-[var(--muted)] font-bold">{label}</div>
      <div className={`font-display text-5xl mt-2 ${colors[accent]}`}>{value}</div>
      <div className="text-xs text-[var(--muted)] mt-1">{sub}</div>
    </div>
  );
}

// Imprime un ticket 80 mm — mise en page définie une seule fois dans caisse/ticket.js.
// genre : 'cuisine' (sans prix, pour le passe) ou 'client' (l'addition).
function printOrder(commande, genre) {
  if (typeof imprimerTicket !== 'function') {
    alert("Le module d'impression n'est pas chargé.");
    return;
  }
  imprimerTicket(commande, SHOP, genre || 'cuisine');
}

function OrderCard({ commande, onAdvance, onCancel }) {
  const etat = STATUTS[commande.statut] || STATUTS.nouvelle;
  const mode = MODES[commande.mode] || MODES.emporter;
  const qrAValider = commande.mode === 'surplace' && commande.origine === 'qr' && commande.statut === 'nouvelle';
  const appelAValider = !!commande.attenteAppel && commande.statut === 'nouvelle';
  const heure = commande.recueA
    ? new Date(commande.recueA).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })
    : '';
  return (
    <div className="admin-card hover:border-[var(--vert)] transition-colors">
      <div className="flex items-start justify-between gap-3 flex-wrap">
        <div>
          <div className="flex items-center gap-2 mb-1.5 flex-wrap">
            <span className={`mode-chip ${commande.mode}`}>
              {mode.ticket}{commande.table ? ` · TABLE ${commande.table}` : ''}
            </span>
            <span className="font-display text-xl text-[var(--vert)]">{commande.numero}</span>
            <span className="text-xs text-[var(--muted)]">· {heure}</span>
          </div>
          <div className="font-bold">
            {commande.mode === 'surplace' ? `Table ${commande.table || '?'}` : (commande.client?.nom || 'Client')}
            {commande.client?.tel && <span className="font-normal text-[var(--muted)]"> · {commande.client.tel}</span>}
          </div>
          {commande.client?.adresse && <div className="text-xs text-[var(--cream-2)] mt-1">{commande.client.adresse}</div>}
          {commande.heureRetrait && <div className="text-xs text-[var(--cream-2)] mt-1">Retrait à {commande.heureRetrait}</div>}
        </div>
        <span className={`admin-status ${etat.css}`}>
          <span className={`w-1.5 h-1.5 rounded-full bg-current ${commande.statut === 'nouvelle' ? 'pulse-dot' : ''}`}/>
          {qrAValider ? 'À vérifier · QR' : appelAValider ? 'Attente de l’appel' : etat.label}
        </span>
      </div>

      {appelAValider && (
        <div className="mt-3 text-sm bg-[var(--or)]/10 border border-[var(--or)]/30 rounded-xl p-2.5">
          <strong>Espèces : attendre l’appel du client</strong>{commande.client?.tel ? ` (${commande.client.tel})` : ''}. Ne pas préparer avant.
          Quand il a appelé, confirme ; sans appel, annule.
        </div>
      )}
      {qrAValider && (
        <div className="mt-3 text-sm bg-[var(--or)]/10 border border-[var(--or)]/30 rounded-xl p-2.5">
          Vérifie que la table {commande.table || '?'} est bien occupée avant d’envoyer le ticket en cuisine.
        </div>
      )}

      <ul className="mt-3 pt-3 border-t border-[var(--line)] space-y-1.5 text-sm">
        {(commande.lignes || []).map((l, i) => (
          <li key={i}>
            <div className="flex justify-between gap-3">
              <span><strong className="text-[var(--cream)]">{l.qte}×</strong> {l.nom}</span>
              <span className="text-[var(--muted)] shrink-0">{(l.prixUnitaire * l.qte).toFixed(2)}€</span>
            </div>
            {l.options && (
              <div className="text-[11px] text-[var(--muted)] pl-5">
                {Object.entries(l.options).map(([k, v]) => `${k} : ${v}`).join(' · ')}
              </div>
            )}
          </li>
        ))}
      </ul>

      {commande.note && (
        <div className="mt-3 text-sm bg-[var(--rouge)]/12 border border-[var(--rouge)]/30 text-[var(--cream)] rounded-xl p-2.5">
          <strong className="text-[var(--rouge-2)]">Note :</strong> {commande.note}
        </div>
      )}

      <div className="mt-3 pt-3 border-t border-[var(--line)] flex items-center justify-between gap-2 flex-wrap">
        <div className="font-display text-xl text-[var(--vert)]">
          {Number(commande.total).toFixed(2)}€
          <span className={`ml-2 text-[11px] font-sans font-bold uppercase tracking-wider ${commande.paiement?.paye ? 'text-[var(--jade)]' : 'text-[var(--rouge-2)]'}`}>
            {commande.paiement?.paye ? 'payé' : 'à encaisser'}
          </span>
        </div>
        <div className="flex gap-2 flex-wrap">
          {(qrAValider || appelAValider) ? (
            <>
              <button onClick={onAdvance} className="btn btn-primary !py-2 !px-4 !text-xs">
                {appelAValider ? 'Le client a appelé · envoyer en cuisine →' : 'Présence vérifiée · envoyer en cuisine →'}
              </button>
              {appelAValider && commande.client?.tel && (
                <a href={`tel:${String(commande.client.tel).replace(/\s/g, '')}`} className="btn btn-ghost !py-2 !px-3 !text-xs" title="Appeler le client">
                  <Icon.Phone className="w-3.5 h-3.5"/>
                </a>
              )}
              <button onClick={onCancel} className="btn btn-ghost !py-2 !px-3 !text-xs">Annuler la commande</button>
            </>
          ) : commande.statut !== 'annulee' && (
            <>
              <button onClick={() => printOrder(commande, 'cuisine')} className="btn btn-ghost !py-2 !px-3 !text-xs" title="Ticket cuisine, sans les prix">
                <Icon.Printer className="w-3.5 h-3.5"/> Cuisine
              </button>
              <button onClick={() => printOrder(commande, 'client')} className="btn btn-ghost !py-2 !px-3 !text-xs" title="Ticket de caisse, avec les prix et le total — à donner une fois le client payé">
                <Icon.Printer className="w-3.5 h-3.5"/> Caisse
              </button>
              {commande.client?.tel && (
                <a href={`tel:${String(commande.client.tel).replace(/\s/g, '')}`} className="btn btn-ghost !py-2 !px-3 !text-xs" title="Appeler le client">
                  <Icon.Phone className="w-3.5 h-3.5"/>
                </a>
              )}
              {etat.bouton && (
                <button onClick={onAdvance} className="btn btn-primary !py-2 !px-4 !text-xs">
                  {etat.bouton} →
                </button>
              )}
              {commande.statut !== 'terminee' && (
                <button onClick={onCancel} className="btn btn-ghost !py-2 !px-3 !text-xs">Annuler</button>
              )}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CartDrawer, CheckoutModal, AdminView, ModeOption, Field, ConfirmedView, OrderCard, StatCard, printOrder, STATUTS });
