import { NextResponse } from 'next/server';
import { wrapRouteHandler } from '@server/logger/request';

const WIDGET_SCRIPT = `
(function() {
  'use strict';

  var script = document.currentScript || (function() {
    var scripts = document.getElementsByTagName('script');
    for (var i = scripts.length - 1; i >= 0; i--) {
      if (scripts[i].src && scripts[i].src.indexOf('/api/widget/embed.js') >= 0) {
        return scripts[i];
      }
    }
    return scripts[scripts.length - 1];
  })();

  var _srcStr = (script && script.src) ? script.src : '';
  var _qIdx = _srcStr.indexOf('?');
  var _srcParams = _qIdx >= 0 ? new URLSearchParams(_srcStr.slice(_qIdx + 1)) : new URLSearchParams();
  var restaurantId = _srcParams.get('rid') || (script ? script.getAttribute('data-restaurant-id') : null);
  var _cleanSrc = _qIdx >= 0 ? _srcStr.slice(0, _qIdx) : _srcStr;
  var baseUrl = (script ? script.getAttribute('data-base-url') : null) || (_cleanSrc ? _cleanSrc.replace('/api/widget/embed.js', '') : window.location.origin);

  if (!restaurantId) {
    console.warn('[RestroAgent Widget] Missing restaurant ID. Add ?rid=YOUR_ID to the script src.');
    return;
  }

  var SESSION_KEY = 'ra_widget_session_' + restaurantId;
  var HISTORY_KEY = 'ra_widget_history_' + restaurantId;

  var state = {
    sessionToken: null,
    conversationId: null,
    restaurantName: 'Our Restaurant',
    settings: null,
    messages: [],
    isOpen: false,
    isLoading: false,
    hasStarted: false,
    cart: {},
    menuData: null,
    activeCategory: null,
    bookingStep: -1,
    bookingData: {},
    sessionGeneration: 0,
  };

  function loadSession() {
    try {
      var saved = localStorage.getItem(SESSION_KEY);
      if (saved) {
        var parsed = JSON.parse(saved);
        state.sessionToken = parsed.sessionToken;
        state.conversationId = parsed.conversationId;
      }
      var hist = localStorage.getItem(HISTORY_KEY);
      if (hist) state.messages = JSON.parse(hist);
    } catch(e) {}
  }

  function saveSession() {
    try {
      localStorage.setItem(SESSION_KEY, JSON.stringify({
        sessionToken: state.sessionToken,
        conversationId: state.conversationId,
      }));
      localStorage.setItem(HISTORY_KEY, JSON.stringify(state.messages.slice(-50)));
    } catch(e) {}
  }

  var host, shadow, container, chatPanel, msgList, inputEl, sendBtn, badge, bubble;
  var cartBar, cartBarCount, cartBarTotal;
  var primaryColor = '#f97316';
  var botName = 'AI Assistant';
  var widgetIsLeft = false;

  function getCartCount() {
    return Object.values(state.cart).reduce(function(s, i) { return s + i.qty; }, 0);
  }
  function getCartTotal() {
    return Object.values(state.cart).reduce(function(s, i) { return s + i.price * i.qty; }, 0);
  }

  function hexToRgb(hex) {
    var r = parseInt(hex.slice(1,3),16);
    var g = parseInt(hex.slice(3,5),16);
    var b = parseInt(hex.slice(5,7),16);
    return r + ',' + g + ',' + b;
  }

  function darken(hex, amt) {
    var num = parseInt(hex.replace('#',''), 16);
    var r = Math.max(0, (num >> 16) - amt);
    var g = Math.max(0, ((num >> 8) & 0xff) - amt);
    var b = Math.max(0, (num & 0xff) - amt);
    return '#' + ((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1);
  }

  function escHtml(s) {
    return String(s || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  }

  function now() {
    return new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  }

  function initShadow() {
    var pos = (state.settings && state.settings.position) || 'bottom-right';
    widgetIsLeft = pos === 'bottom-left';
    host = document.createElement('div');
    host.id = 'ra-widget-host';
    host.style.cssText = 'position:fixed;z-index:2147483647;bottom:24px;' + (widgetIsLeft ? 'left:24px;' : 'right:24px;') + 'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;';
    document.body.appendChild(host);
    shadow = host.attachShadow({ mode: 'open' });

    var style = document.createElement('style');
    style.textContent = getStyles();
    shadow.appendChild(style);

    container = document.createElement('div');
    container.id = 'ra-container';
    shadow.appendChild(container);
    renderWidget();
  }

  function getStyles() {
    var pc = primaryColor;
    var rgb = hexToRgb(pc);
    var dark = darken(pc, 30);
    return \`
      * { box-sizing: border-box; margin: 0; padding: 0; }

      #ra-bubble {
        width: 60px; height: 60px;
        background: linear-gradient(135deg, \${pc}, \${dark});
        border-radius: 50%;
        cursor: pointer;
        display: flex; align-items: center; justify-content: center;
        box-shadow: 0 4px 20px rgba(\${rgb}, 0.4), 0 2px 8px rgba(0,0,0,0.15);
        transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.2s ease;
        position: relative; user-select: none;
      }
      #ra-bubble:hover { transform: scale(1.08); box-shadow: 0 6px 28px rgba(\${rgb}, 0.5), 0 3px 12px rgba(0,0,0,0.2); }
      #ra-bubble:active { transform: scale(0.95); }
      #ra-bubble svg { width: 28px; height: 28px; fill: white; transition: opacity 0.2s; }

      #ra-badge {
        position: absolute; top: -4px; right: -4px;
        width: 20px; height: 20px;
        background: #ef4444; color: white;
        border-radius: 50%; font-size: 11px; font-weight: 700;
        display: flex; align-items: center; justify-content: center;
        border: 2px solid white;
        animation: ra-pulse 2s infinite;
      }
      @keyframes ra-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }

      #ra-panel {
        position: absolute; bottom: 72px; \${widgetIsLeft ? 'left: 0;' : 'right: 0;'}
        width: 370px; height: 580px;
        background: #fff;
        border-radius: 20px;
        box-shadow: 0 20px 60px rgba(0,0,0,0.15), 0 8px 24px rgba(0,0,0,0.1);
        display: flex; flex-direction: column;
        overflow: hidden;
        transform-origin: \${widgetIsLeft ? 'bottom left' : 'bottom right'};
        transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), opacity 0.25s ease;
      }
      #ra-panel.hidden { transform: scale(0.8); opacity: 0; pointer-events: none; }
      #ra-panel.visible { transform: scale(1); opacity: 1; }

      @media (max-width: 420px) {
        #ra-panel { width: 100vw; height: 100vh; border-radius: 0; bottom: 0; right: 0; position: fixed; }
      }

      #ra-header {
        background: linear-gradient(135deg, \${pc}, \${dark});
        padding: 14px 16px;
        display: flex; align-items: center; gap: 10px;
        flex-shrink: 0;
      }
      .ra-avatar {
        width: 38px; height: 38px;
        background: rgba(255,255,255,0.2);
        border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        font-size: 18px; flex-shrink: 0; overflow: hidden;
      }
      .ra-header-text { flex: 1; min-width: 0; }
      .ra-header-name { color: white; font-weight: 700; font-size: 15px; }
      .ra-header-status { color: rgba(255,255,255,0.8); font-size: 12px; display: flex; align-items: center; gap: 5px; margin-top: 1px; }
      .ra-status-dot { width: 7px; height: 7px; background: #4ade80; border-radius: 50%; animation: ra-blink 2s infinite; }
      @keyframes ra-blink { 0%,100%{opacity:1} 50%{opacity:0.4} }
      #ra-close {
        background: rgba(255,255,255,0.15); border: none; cursor: pointer;
        width: 30px; height: 30px; border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        color: white; transition: background 0.2s; flex-shrink: 0;
      }
      #ra-close:hover { background: rgba(255,255,255,0.25); }
      #ra-close svg { width: 16px; height: 16px; fill: white; }

      #ra-new-chat {
        background: rgba(255,255,255,0.15); border: none; cursor: pointer;
        height: 28px; border-radius: 14px; padding: 0 10px;
        display: flex; align-items: center; gap: 4px;
        color: white; font-size: 11px; font-weight: 600; font-family: inherit;
        transition: background 0.2s; flex-shrink: 0; white-space: nowrap;
      }
      #ra-new-chat:hover { background: rgba(255,255,255,0.28); }
      #ra-new-chat svg { width: 13px; height: 13px; fill: white; }

      #ra-messages {
        flex: 1; overflow-y: auto; padding: 14px 12px;
        display: flex; flex-direction: column; gap: 10px;
        scroll-behavior: smooth;
      }
      #ra-messages::-webkit-scrollbar { width: 4px; }
      #ra-messages::-webkit-scrollbar-track { background: transparent; }
      #ra-messages::-webkit-scrollbar-thumb { background: #e5e7eb; border-radius: 2px; }

      .ra-msg-wrap { display: flex; gap: 8px; align-items: flex-end; }
      .ra-msg-wrap.customer { flex-direction: row-reverse; }

      .ra-msg-icon {
        width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
        display: flex; align-items: center; justify-content: center;
        font-size: 12px; font-weight: 700; color: white;
      }
      .ra-msg-icon.ai { background: linear-gradient(135deg, \${pc}, \${dark}); }
      .ra-msg-icon.customer { background: linear-gradient(135deg, #6366f1, #4338ca); }
      .ra-msg-icon svg { width: 14px; height: 14px; fill: white; }

      .ra-bubble-msg {
        max-width: 75%; min-width: fit-content; padding: 10px 14px;
        font-size: 13px; line-height: 1.5;
        word-break: break-word;
      }
      .ra-bubble-msg.ai {
        background: #f3f4f6; color: #111827;
        border-radius: 4px 16px 16px 16px;
      }
      .ra-bubble-msg.customer {
        background: linear-gradient(135deg, \${pc}, \${dark}); color: white;
        border-radius: 16px 4px 16px 16px;
      }
      .ra-msg-time { font-size: 10px; color: #9ca3af; margin-top: 3px; }

      .ra-typing { display: flex; gap: 4px; align-items: center; padding: 12px 16px; background: #f3f4f6; border-radius: 4px 16px 16px 16px; }
      .ra-typing span {
        width: 7px; height: 7px; border-radius: 50%; background: #d1d5db;
        animation: ra-typing 1.2s infinite;
      }
      .ra-typing span:nth-child(2) { animation-delay: 0.2s; }
      .ra-typing span:nth-child(3) { animation-delay: 0.4s; }
      @keyframes ra-typing { 0%,60%,100%{transform:translateY(0)} 30%{transform:translateY(-6px)} }

      .ra-system-msg {
        text-align: center; font-size: 11px; color: #9ca3af;
        padding: 4px 12px; background: #f9fafb; border-radius: 8px;
        align-self: center;
      }

      .ra-action-card {
        background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 10px;
        padding: 10px 12px; font-size: 12px; color: #15803d;
        display: flex; align-items: center; gap: 6px; margin-top: 2px;
      }
      .ra-action-card svg { width: 14px; height: 14px; fill: #16a34a; flex-shrink: 0; }

      /* Rejection cards (per-item) */
      .ra-reject-wrap {
        background: #fff7ed; border: 1px solid #fed7aa; border-radius: 12px;
        padding: 10px 12px; margin-top: 2px; max-width: 85%;
        display: flex; flex-direction: column; gap: 8px;
      }
      .ra-reject-head {
        display: flex; align-items: center; gap: 7px;
        font-size: 12px; font-weight: 700; color: #9a3412;
      }
      .ra-reject-head svg { width: 15px; height: 15px; fill: #ea580c; flex-shrink: 0; }
      .ra-reject-list { display: flex; flex-direction: column; gap: 6px; }
      .ra-reject-item {
        background: #fff; border: 1px solid #fed7aa; border-radius: 9px;
        padding: 8px 10px;
        display: flex; align-items: flex-start; gap: 8px;
      }
      .ra-reject-icon {
        width: 22px; height: 22px; border-radius: 50%;
        background: #fff7ed; flex-shrink: 0;
        display: flex; align-items: center; justify-content: center;
      }
      .ra-reject-icon svg { width: 12px; height: 12px; fill: #ea580c; }
      .ra-reject-body { flex: 1; min-width: 0; }
      .ra-reject-name {
        font-size: 12px; font-weight: 700; color: #111827;
        line-height: 1.3; word-break: break-word;
      }
      .ra-reject-reason {
        display: inline-block; margin-top: 3px;
        background: #fed7aa; color: #9a3412;
        padding: 1px 7px; border-radius: 8px;
        font-size: 10px; font-weight: 600; letter-spacing: 0.01em;
      }
      .ra-reject-msg {
        font-size: 11px; color: #6b7280; margin-top: 4px; line-height: 1.4;
      }
      .ra-reject-actions {
        display: flex; gap: 6px; flex-wrap: wrap;
      }
      .ra-reject-btn {
        background: \${pc}; color: white; border: none; border-radius: 8px;
        padding: 6px 12px; font-size: 11px; font-weight: 600; cursor: pointer;
        font-family: inherit; transition: background 0.15s;
      }
      .ra-reject-btn:hover { background: \${dark}; }
      .ra-reject-btn.secondary {
        background: #fff; color: #374151; border: 1px solid #e5e7eb;
      }
      .ra-reject-btn.secondary:hover { background: #f9fafb; border-color: #d1d5db; }

      /* Quick reply chips */
      .ra-chips-row {
        display: flex; flex-wrap: wrap; gap: 7px;
        padding: 2px 0; margin-left: 36px;
      }
      .ra-chips-row.ra-ai-chips { margin-left: 36px; }
      .ra-chip {
        background: #fff; border: 1.5px solid #e5e7eb; border-radius: 20px;
        padding: 6px 13px; font-size: 12px; color: #374151;
        cursor: pointer; transition: all 0.15s; white-space: nowrap;
        font-family: inherit; line-height: 1.3;
      }
      .ra-chip:hover:not(:disabled) { background: \${pc}; color: white; border-color: \${pc}; }
      .ra-chip:disabled { opacity: 0.5; cursor: default; }
      .ra-chip-primary { background: \${pc}; color: white; border-color: \${pc}; }
      .ra-chip-primary:hover:not(:disabled) { background: \${dark}; border-color: \${dark}; }

      /* Menu view */
      .ra-menu-view {
        background: #f9fafb; border: 1.5px solid #e5e7eb; border-radius: 14px;
        overflow: visible; width: 100%;
      }
      .ra-menu-header {
        display: flex; align-items: center; justify-content: space-between;
        padding: 9px 12px; background: \${pc}; color: white;
        border-radius: 12px 12px 0 0; overflow: hidden;
      }
      .ra-menu-title { font-weight: 700; font-size: 13px; }
      .ra-menu-close {
        background: rgba(255,255,255,0.2); border: none; cursor: pointer;
        color: white; font-size: 13px; width: 22px; height: 22px;
        border-radius: 50%; display: flex; align-items: center; justify-content: center;
      }
      .ra-menu-close:hover { background: rgba(255,255,255,0.35); }

      .ra-cat-tabs {
        display: flex; gap: 4px; padding: 8px 8px 6px;
        overflow-x: auto; background: #fff; border-bottom: 1px solid #f3f4f6;
        scrollbar-width: thin; scrollbar-color: #d1d5db transparent;
        -webkit-overflow-scrolling: touch;
      }
      .ra-cat-tabs::-webkit-scrollbar { height: 3px; }
      .ra-cat-tabs::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 2px; }
      .ra-cat-tab {
        background: transparent; border: 1.5px solid #e5e7eb;
        border-radius: 16px; padding: 4px 10px; font-size: 11px;
        color: #6b7280; cursor: pointer; white-space: nowrap;
        font-family: inherit; transition: all 0.15s; flex-shrink: 0;
      }
      .ra-cat-tab.active { background: \${pc}; color: white; border-color: \${pc}; font-weight: 600; }
      .ra-cat-tab:hover:not(.active) { border-color: \${pc}; color: \${pc}; }

      .ra-items-list { max-height: 210px; overflow-y: auto; padding: 6px; scrollbar-width: thin; }
      .ra-items-list::-webkit-scrollbar { width: 3px; }
      .ra-items-list::-webkit-scrollbar-thumb { background: #e5e7eb; border-radius: 2px; }

      .ra-item-card {
        display: flex; align-items: center; gap: 8px;
        padding: 8px 6px; margin-bottom: 4px;
        background: #fff; border-radius: 10px; border: 1px solid #f3f4f6;
      }
      .ra-item-card:last-child { margin-bottom: 0; }
      .ra-item-img { width: 46px; height: 46px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
      .ra-item-info { flex: 1; min-width: 0; }
      .ra-item-name { font-size: 12px; font-weight: 600; color: #111827; }
      .ra-item-desc { font-size: 11px; color: #9ca3af; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
      .ra-item-price { font-size: 12px; font-weight: 700; color: \${pc}; margin-top: 2px; }
      .ra-item-qty { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
      .ra-add-btn {
        background: \${pc}; color: white; border: none; border-radius: 7px;
        padding: 4px 9px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 600;
      }
      .ra-add-btn:hover { background: \${dark}; }
      .ra-qty-btn {
        width: 22px; height: 22px; background: #f3f4f6; border: none; border-radius: 50%;
        cursor: pointer; display: flex; align-items: center; justify-content: center;
        font-size: 14px; font-weight: 700; color: #374151; line-height: 1;
      }
      .ra-qty-btn:hover { background: #e5e7eb; }
      .ra-qty-num { font-size: 12px; font-weight: 700; color: #111827; min-width: 16px; text-align: center; }

      .ra-view-cart-btn {
        display: none; align-items: center; justify-content: center; gap: 6px;
        width: 100%; padding: 10px 12px; background: #111827; color: white;
        border: none; cursor: pointer; font-size: 12px; font-weight: 700;
        font-family: inherit;
      }
      .ra-view-cart-btn:hover { background: #1f2937; }

      /* Cart bar */
      #ra-cart-bar {
        display: none; flex-shrink: 0;
        background: #111827; color: white;
        padding: 9px 12px; align-items: center; gap: 8px;
      }
      .ra-cart-bar-info { flex: 1; font-size: 12px; color: rgba(255,255,255,0.85); }
      .ra-cart-bar-info strong { color: white; font-size: 13px; }
      .ra-cart-bar-order {
        background: \${pc}; color: white; border: none; border-radius: 8px;
        padding: 6px 12px; font-size: 12px; font-weight: 700; cursor: pointer;
        font-family: inherit; white-space: nowrap;
      }
      .ra-cart-bar-order:hover { background: \${dark}; }
      .ra-cart-bar-view {
        background: transparent; color: rgba(255,255,255,0.6); border: none;
        font-size: 11px; cursor: pointer; font-family: inherit; text-decoration: underline;
        white-space: nowrap;
      }
      .ra-cart-bar-view:hover { color: white; }

      /* Cart summary */
      .ra-cart-summary {
        background: #f9fafb; border: 1.5px solid #e5e7eb; border-radius: 12px;
        padding: 12px; width: 100%;
      }
      .ra-cart-title { font-weight: 700; font-size: 13px; color: #111827; margin-bottom: 8px; }
      .ra-cart-line {
        display: flex; justify-content: space-between; font-size: 12px; color: #374151; padding: 2px 0;
      }
      .ra-cart-total { font-weight: 700; font-size: 13px; color: #111827; margin-top: 8px; padding-top: 8px; border-top: 1px solid #e5e7eb; }

      /* Booking flow */
      .ra-booking-step { width: 100%; }
      .ra-booking-q { font-size: 13px; font-weight: 600; color: #374151; margin-bottom: 8px; }
      .ra-booking-input-row { display: flex; gap: 7px; align-items: center; margin-top: 6px; }
      .ra-booking-input {
        flex: 1; border: 1.5px solid #e5e7eb; border-radius: 9px;
        padding: 7px 11px; font-size: 12px; font-family: inherit;
        outline: none; color: #111827; background: #fafafa;
      }
      .ra-booking-input:focus { border-color: \${pc}; background: #fff; }
      .ra-booking-confirm { background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 10px; padding: 10px 12px; margin-bottom: 10px; }
      .ra-booking-title { font-weight: 700; font-size: 12px; color: #1d4ed8; margin-bottom: 6px; }
      .ra-booking-line { font-size: 12px; color: #374151; padding: 2px 0; }

      #ra-footer {
        padding: 10px 12px;
        border-top: 1px solid #f3f4f6;
        display: flex; gap: 8px; align-items: flex-end; flex-shrink: 0;
        background: #fff;
      }
      #ra-input {
        flex: 1; border: 1.5px solid #e5e7eb; border-radius: 12px;
        padding: 9px 13px; font-size: 13px; font-family: inherit;
        outline: none; resize: none; max-height: 90px;
        transition: border-color 0.2s; color: #111827; background: #fafafa;
        line-height: 1.4;
      }
      #ra-input:focus { border-color: \${pc}; background: #fff; }
      #ra-input::placeholder { color: #9ca3af; }

      #ra-send {
        width: 38px; height: 38px;
        background: linear-gradient(135deg, \${pc}, \${dark}); border: none;
        border-radius: 10px; cursor: pointer;
        display: flex; align-items: center; justify-content: center;
        transition: transform 0.15s, box-shadow 0.15s; flex-shrink: 0;
        box-shadow: 0 2px 8px rgba(\${rgb}, 0.35);
      }
      #ra-send:hover:not(:disabled) { transform: scale(1.05); box-shadow: 0 4px 12px rgba(\${rgb}, 0.45); }
      #ra-send:active:not(:disabled) { transform: scale(0.95); }
      #ra-send:disabled { opacity: 0.5; cursor: default; transform: none; box-shadow: none; }
      #ra-send svg { width: 17px; height: 17px; fill: white; }

      #ra-branding {
        text-align: center; font-size: 10px; color: #d1d5db; padding: 5px 16px 7px;
        background: #fff; flex-shrink: 0;
      }
      #ra-branding a { color: #9ca3af; text-decoration: none; }
      #ra-branding a:hover { color: #6b7280; }
    \`;
  }

  function svgChat() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>';
  }
  function svgNewChat() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 13H13v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>';
  }
  function svgClose() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>';
  }
  function svgSend() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>';
  }
  function svgBot() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a2 2 0 012 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 017 7H3a7 7 0 017-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 012-2zM7.5 15.5a1 1 0 100 2 1 1 0 000-2zm9 0a1 1 0 100 2 1 1 0 000-2zM12 18c-2.09 0-3.9.72-4.95 1.78A9.95 9.95 0 0012 22c2.57 0 4.9-.97 6.66-2.55A7.17 7.17 0 0012 18z"/></svg>';
  }
  function svgCheck() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg>';
  }
  function svgWarn() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>';
  }
  function svgClock() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 110-16 8 8 0 010 16zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67V7z"/></svg>';
  }
  function svgQuestion() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M11 18h2v-2h-2v2zm1-16a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 110-16 8 8 0 010 16zm0-14a4 4 0 00-4 4h2a2 2 0 014 0c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5a4 4 0 00-4-4z"/></svg>';
  }
  function svgBan() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 01-5.66-2.34L17.66 6.34A8 8 0 0112 20zM4.34 17.66A8 8 0 0112 4a8 8 0 015.66 2.34L4.34 17.66z"/></svg>';
  }
  function svgPin() {
    return '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5a2.5 2.5 0 110-5 2.5 2.5 0 010 5z"/></svg>';
  }

  function svgRejectIcon(reason) {
    if (reason === 'out_of_stock') return svgBan();
    if (reason === 'off_schedule') return svgClock();
    if (reason === 'unknown_item') return svgQuestion();
    if (reason === 'wrong_branch') return svgPin();
    return svgWarn();
  }

  function renderWidget() {
    var s = state.settings;
    var pc = s ? s.primary_color : '#f97316';
    var wm = s ? s.welcome_message : '';
    var name = state.restaurantName || (s ? s.bot_name : 'AI Assistant');
    var subLabel = s ? s.bot_name : 'AI Assistant';
    var ph = s ? s.placeholder_text : 'Type your message...';
    var iconUrl = s ? s.icon_url : null;
    if (iconUrl && iconUrl.charAt(0) === '/') iconUrl = baseUrl + iconUrl;
    var avatarHtml = iconUrl
      ? '<img src="' + escHtml(iconUrl) + '" alt="Bot" style="width:100%;height:100%;object-fit:cover;border-radius:50%;" />'
      : '\\uD83C\\uDF7D\\uFE0F';

    container.innerHTML =
      '<div id="ra-bubble">' + svgChat() + '<div id="ra-badge" style="display:none"></div></div>' +
      '<div id="ra-panel" class="hidden">' +
        '<div id="ra-header">' +
          '<div class="ra-avatar">' + avatarHtml + '</div>' +
          '<div class="ra-header-text">' +
            '<div class="ra-header-name">' + escHtml(name) + '</div>' +
            '<div class="ra-header-status"><span class="ra-status-dot"></span> ' + escHtml(subLabel) + ' · Online</div>' +
          '</div>' +
          '<button id="ra-new-chat" aria-label="Start new conversation">' + svgNewChat() + 'New Chat</button>' +
          '<button id="ra-close" aria-label="Close">' + svgClose() + '</button>' +
        '</div>' +
        '<div id="ra-messages"></div>' +
        '<div id="ra-cart-bar">' +
          '<div class="ra-cart-bar-info">\\uD83D\\uDED2 <strong><span id="ra-cbc">0</span></strong> item(s) · $<strong><span id="ra-cbt">0.00</span></strong></div>' +
          '<button class="ra-cart-bar-view" id="ra-cbv">View</button>' +
          '<button class="ra-cart-bar-order" id="ra-cbo">Place Order</button>' +
        '</div>' +
        '<div id="ra-footer">' +
          '<textarea id="ra-input" rows="1" placeholder="' + escHtml(ph) + '" maxlength="1000"></textarea>' +
          '<button id="ra-send" aria-label="Send">' + svgSend() + '</button>' +
        '</div>' +
        '<div id="ra-branding">Powered by <a href="__RA_BRAND_URL__" target="_blank" rel="noopener">__RA_BRAND_NAME__</a></div>' +
      '</div>';

    bubble = container.querySelector('#ra-bubble');
    chatPanel = container.querySelector('#ra-panel');
    msgList = container.querySelector('#ra-messages');
    inputEl = container.querySelector('#ra-input');
    sendBtn = container.querySelector('#ra-send');
    badge = container.querySelector('#ra-badge');
    cartBar = container.querySelector('#ra-cart-bar');
    cartBarCount = container.querySelector('#ra-cbc');
    cartBarTotal = container.querySelector('#ra-cbt');

    bubble.addEventListener('click', togglePanel);
    container.querySelector('#ra-close').addEventListener('click', closePanel);
    container.querySelector('#ra-new-chat').addEventListener('click', startOver);
    sendBtn.addEventListener('click', sendMessage);
    inputEl.addEventListener('keydown', function(e) {
      if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); }
    });
    inputEl.addEventListener('input', function() {
      this.style.height = 'auto';
      this.style.height = Math.min(this.scrollHeight, 90) + 'px';
    });
    container.querySelector('#ra-cbo').addEventListener('click', placeOrderFromCart);
    container.querySelector('#ra-cbv').addEventListener('click', showCartSummary);

    if (state.messages.length > 0) {
      renderAllMessages();
      updateCartBar();
    } else if (wm) {
      setTimeout(function() {
        addMessage({ sender: 'ai', content: wm, time: now() }, false);
        setTimeout(showInitialChips, 250);
      }, 200);
    } else {
      setTimeout(showInitialChips, 200);
    }
  }

  /* ─── Initial action chips ─────────────────────────── */

  function showInitialChips() {
    if (!msgList) return;
    var existing = container.querySelector('#ra-initial-chips');
    if (existing) return;
    var el = document.createElement('div');
    el.className = 'ra-chips-row';
    el.id = 'ra-initial-chips';
    el.style.cssText = 'margin-left:36px;margin-top:2px;';
    var chips = [
      { action: 'order', label: '\\uD83C\\uDF7D\\uFE0F Order Food' },
      { action: 'book',  label: '\\uD83D\\uDCC5 Book a Table' },
      { action: 'ask',   label: '\\uD83D\\uDCAC Ask a Question' },
    ];
    el.innerHTML = chips.map(function(c) {
      return '<button class="ra-chip" data-action="' + c.action + '">' + c.label + '</button>';
    }).join('');
    msgList.appendChild(el);
    scrollToBottom();

    el.querySelectorAll('.ra-chip').forEach(function(chip) {
      chip.addEventListener('click', function() {
        var action = chip.getAttribute('data-action');
        el.remove();
        if (action === 'order') {
          openMenuView();
        } else if (action === 'book') {
          state.bookingStep = 0;
          state.bookingData = {};
          showBookingStep();
        } else {
          if (inputEl) { inputEl.placeholder = 'What would you like to know?'; inputEl.focus(); }
          addSystemMessage('Go ahead and type your question below.');
        }
      });
    });
  }

  /* ─── Menu ──────────────────────────────────────────── */

  function openMenuView() {
    var existing = container.querySelector('#ra-menu-view');
    if (existing) {
      existing.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
      return;
    }
    if (state.menuData) { renderMenuInChat(); return; }

    var loadEl = document.createElement('div');
    loadEl.className = 'ra-system-msg';
    loadEl.textContent = 'Loading menu\\u2026';
    loadEl.id = 'ra-menu-loading';
    msgList.appendChild(loadEl);
    scrollToBottom();

    fetch(baseUrl + '/api/widget/menu?restaurantId=' + restaurantId)
      .then(function(r) { return r.json(); })
      .then(function(data) {
        var loader = container.querySelector('#ra-menu-loading');
        if (loader) loader.remove();
        state.menuData = (data.categories && data.categories.length > 0) ? data : { categories: [] };
        state.activeCategory = state.menuData.categories.length > 0 ? state.menuData.categories[0].id : null;
        renderMenuInChat();
      })
      .catch(function() {
        var loader = container.querySelector('#ra-menu-loading');
        if (loader) loader.textContent = 'Could not load menu. Please ask me about our dishes!';
      });
  }

  function renderMenuInChat() {
    if (!state.menuData || state.menuData.categories.length === 0) {
      addSystemMessage('Our digital menu is not set up yet. Feel free to ask me about our dishes!');
      return;
    }

    var menuEl = document.createElement('div');
    menuEl.id = 'ra-menu-view';
    menuEl.className = 'ra-menu-view';

    var tabsHtml = state.menuData.categories.map(function(cat) {
      var active = cat.id === state.activeCategory ? ' active' : '';
      return '<button class="ra-cat-tab' + active + '" data-cat="' + escHtml(cat.id) + '">' + escHtml(cat.name) + '</button>';
    }).join('');

    menuEl.innerHTML =
      '<div class="ra-menu-header">' +
        '<span class="ra-menu-title">\\uD83D\\uDCCB Our Menu</span>' +
        '<button class="ra-menu-close">&#x2715;</button>' +
      '</div>' +
      '<div class="ra-cat-tabs">' + tabsHtml + '</div>' +
      '<div class="ra-items-list"></div>' +
      '<button class="ra-view-cart-btn">' +
        '\\uD83D\\uDED2 Place Order &middot; <span class="vc-count">0</span> items &middot; $<span class="vc-total">0.00</span>' +
      '</button>';

    msgList.appendChild(menuEl);
    scrollToBottom();

    var itemsList = menuEl.querySelector('.ra-items-list');
    var vcBtn = menuEl.querySelector('.ra-view-cart-btn');

    function refreshItems() {
      var cat = null;
      for (var i = 0; i < state.menuData.categories.length; i++) {
        if (state.menuData.categories[i].id === state.activeCategory) { cat = state.menuData.categories[i]; break; }
      }
      if (!cat || !itemsList) return;

      var avail = cat.items.filter(function(it) { return it.is_available; });
      if (avail.length === 0) {
        itemsList.innerHTML = '<div style="padding:14px;text-align:center;color:#9ca3af;font-size:12px;">No items available in this category.</div>';
        return;
      }

      itemsList.innerHTML = avail.map(function(item) {
        var qty = state.cart[item.id] ? state.cart[item.id].qty : 0;
        var imgH = item.image_url ? '<img class="ra-item-img" src="' + escHtml(item.image_url) + '" alt="' + escHtml(item.name) + '" onerror="this.style.display=\\'none\\'" />' : '';
        var vegB = item.is_veg ? '<span style="font-size:10px;color:#16a34a;font-weight:600;margin-left:4px;">\\uD83C\\uDF3F</span>' : '';
        var desc = item.description ? (item.description.length > 50 ? item.description.slice(0,50) + '\\u2026' : item.description) : '';
        var qtyH = qty > 0
          ? '<button class="ra-qty-btn ra-qty-minus" data-id="' + item.id + '">\\u2212</button>' +
            '<span class="ra-qty-num">' + qty + '</span>' +
            '<button class="ra-qty-btn ra-qty-plus" data-id="' + item.id + '" data-name="' + escHtml(item.name) + '" data-price="' + item.price + '">+</button>'
          : '<button class="ra-add-btn" data-id="' + item.id + '" data-name="' + escHtml(item.name) + '" data-price="' + item.price + '">+ Add</button>';

        return '<div class="ra-item-card">' + imgH +
          '<div class="ra-item-info">' +
            '<div class="ra-item-name">' + escHtml(item.name) + vegB + '</div>' +
            (desc ? '<div class="ra-item-desc">' + escHtml(desc) + '</div>' : '') +
            '<div class="ra-item-price">$' + Number(item.price).toFixed(2) + '</div>' +
          '</div>' +
          '<div class="ra-item-qty">' + qtyH + '</div>' +
        '</div>';
      }).join('');

      itemsList.querySelectorAll('.ra-add-btn, .ra-qty-plus').forEach(function(btn) {
        btn.addEventListener('click', function() {
          var id = btn.getAttribute('data-id');
          var nm = btn.getAttribute('data-name');
          var pr = parseFloat(btn.getAttribute('data-price'));
          if (!state.cart[id]) state.cart[id] = { name: nm, price: pr, qty: 0 };
          state.cart[id].qty++;
          refreshItems(); updateCartBar(); refreshVcBtn();
        });
      });
      itemsList.querySelectorAll('.ra-qty-minus').forEach(function(btn) {
        btn.addEventListener('click', function() {
          var id = btn.getAttribute('data-id');
          if (state.cart[id]) {
            state.cart[id].qty--;
            if (state.cart[id].qty <= 0) delete state.cart[id];
            refreshItems(); updateCartBar(); refreshVcBtn();
          }
        });
      });
    }

    function refreshVcBtn() {
      var cnt = getCartCount(), tot = getCartTotal();
      vcBtn.style.display = cnt > 0 ? 'flex' : 'none';
      var cc = vcBtn.querySelector('.vc-count'); if (cc) cc.textContent = cnt;
      var ct = vcBtn.querySelector('.vc-total'); if (ct) ct.textContent = tot.toFixed(2);
    }

    menuEl.querySelectorAll('.ra-cat-tab').forEach(function(tab) {
      tab.addEventListener('click', function() {
        state.activeCategory = tab.getAttribute('data-cat');
        menuEl.querySelectorAll('.ra-cat-tab').forEach(function(t) {
          t.classList.toggle('active', t.getAttribute('data-cat') === state.activeCategory);
        });
        refreshItems();
      });
    });

    menuEl.querySelector('.ra-menu-close').addEventListener('click', function() {
      menuEl.remove(); updateCartBar();
    });

    vcBtn.addEventListener('click', function() { menuEl.remove(); showCartSummary(); });

    refreshItems(); refreshVcBtn();
  }

  function updateCartBar() {
    if (!cartBar) return;
    var cnt = getCartCount(), tot = getCartTotal();
    cartBar.style.display = cnt > 0 ? 'flex' : 'none';
    if (cartBarCount) cartBarCount.textContent = cnt;
    if (cartBarTotal) cartBarTotal.textContent = tot.toFixed(2);
  }

  function showCartSummary() {
    var items = Object.values(state.cart);
    if (items.length === 0) { openMenuView(); return; }
    var tot = getCartTotal();
    var el = document.createElement('div');
    el.className = 'ra-cart-summary';
    el.innerHTML =
      '<div class="ra-cart-title">\\uD83D\\uDED2 Your Order</div>' +
      items.map(function(i) {
        return '<div class="ra-cart-line"><span>' + i.qty + '\\u00D7 ' + escHtml(i.name) + '</span><span>$' + (i.price * i.qty).toFixed(2) + '</span></div>';
      }).join('') +
      '<div class="ra-cart-total">Total &middot; $' + tot.toFixed(2) + '</div>' +
      '<div class="ra-chips-row" style="margin-top:10px;margin-left:0;">' +
        '<button class="ra-chip ra-chip-primary" id="ra-do-order">\\u2705 Place Order</button>' +
        '<button class="ra-chip" id="ra-add-more">+ Add More</button>' +
        '<button class="ra-chip" id="ra-clear-cart" style="color:#ef4444;border-color:#fca5a5;">\\u00D7 Clear Cart</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    el.querySelector('#ra-do-order').addEventListener('click', function() { el.remove(); placeOrderFromCart(); });
    el.querySelector('#ra-add-more').addEventListener('click', function() { el.remove(); openMenuView(); });
    el.querySelector('#ra-clear-cart').addEventListener('click', function() {
      state.cart = {}; el.remove(); updateCartBar();
      addSystemMessage('Cart cleared.');
    });
  }

  function placeOrderFromCart() {
    var items = Object.values(state.cart);
    if (items.length === 0) { openMenuView(); return; }
    showOrderDeliveryStep();
  }

  function showOrderDeliveryStep() {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83D\\uDE9A How would you like your order?</div>' +
      '<div class="ra-chips-row" style="margin-left:0;">' +
        '<button class="ra-chip" data-dt="dine-in">\\uD83C\\uDF7D\\uFE0F Dine-In</button>' +
        '<button class="ra-chip" data-dt="takeaway">\\uD83D\\uDECD\\uFE0F Takeaway</button>' +
        '<button class="ra-chip" data-dt="delivery">\\uD83D\\uDEEB Delivery</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    el.querySelectorAll('.ra-chip[data-dt]').forEach(function(chip) {
      chip.addEventListener('click', function() {
        el.querySelectorAll('button').forEach(function(b) { b.disabled = true; });
        var dt = chip.getAttribute('data-dt');
        var dtLabel = dt === 'dine-in' ? 'Dine-In' : dt === 'takeaway' ? 'Takeaway' : 'Delivery';
        var q = el.querySelector('.ra-booking-q');
        if (q) q.textContent = '\\uD83D\\uDE9A ' + dtLabel + ' \\u2713';
        var cr = el.querySelector('.ra-chips-row'); if (cr) cr.remove();
        if (dt === 'dine-in') { showOrderTableStep(dt); } else if (dt === 'delivery') { showOrderAddressStep(dt); } else { showOrderNameStep(dt, '', ''); }
      });
    });
  }

  function showOrderTableStep(deliveryType) {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83E\\uDE51 Which table are you at?</div>' +
      '<div class="ra-booking-input-row">' +
        '<input type="text" class="ra-booking-input" id="ra-tbl-no" placeholder="e.g. 5" style="max-width:100px;" />' +
        '<button class="ra-chip ra-chip-primary" id="ra-tbl-ok">Next \\u2192</button>' +
        '<button class="ra-chip" id="ra-tbl-skip">No table</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    function proceed(tableNumber) {
      el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
      var q = el.querySelector('.ra-booking-q');
      if (q) q.textContent = tableNumber ? '\\uD83E\\uDE51 Table ' + tableNumber + ' \\u2713' : '\\uD83E\\uDE51 No table \\u2713';
      el.querySelector('.ra-booking-input-row') && el.querySelector('.ra-booking-input-row').remove();
      showOrderNameStep(deliveryType, tableNumber, '');
    }

    var tblOk = el.querySelector('#ra-tbl-ok');
    var tblEl = el.querySelector('#ra-tbl-no');
    var tblSkip = el.querySelector('#ra-tbl-skip');
    if (tblOk && tblEl) {
      tblOk.addEventListener('click', function() { proceed(tblEl.value.trim()); });
      tblEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') tblOk.click(); });
      setTimeout(function() { tblEl.focus(); }, 60);
    }
    if (tblSkip) { tblSkip.addEventListener('click', function() { proceed(''); }); }
  }

  function showOrderAddressStep(deliveryType) {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83D\\uDCCD Your delivery address?</div>' +
      '<div class="ra-booking-input-row">' +
        '<input type="text" class="ra-booking-input" id="ra-order-addr" placeholder="e.g. 123 Main St, City" />' +
        '<button class="ra-chip ra-chip-primary" id="ra-oa-ok">Next \\u2192</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    var oaOk = el.querySelector('#ra-oa-ok');
    var oaEl = el.querySelector('#ra-order-addr');
    if (oaOk && oaEl) {
      oaOk.addEventListener('click', function() {
        var v = oaEl.value.trim();
        if (!v) { oaEl.focus(); return; }
        el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
        var q = el.querySelector('.ra-booking-q');
        if (q) q.textContent = '\\uD83D\\uDCCD ' + v + ' \\u2713';
        el.querySelector('.ra-booking-input-row') && el.querySelector('.ra-booking-input-row').remove();
        showOrderNameStep(deliveryType, '', v);
      });
      oaEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') oaOk.click(); });
      setTimeout(function() { oaEl.focus(); }, 60);
    }
  }

  function showOrderNameStep(deliveryType, tableNumber, deliveryAddress) {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83D\\uDC64 Your name?</div>' +
      '<div class="ra-booking-input-row">' +
        '<input type="text" class="ra-booking-input" id="ra-order-name" placeholder="e.g. John Smith" />' +
        '<button class="ra-chip ra-chip-primary" id="ra-on-ok">Next \\u2192</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    var onOk = el.querySelector('#ra-on-ok');
    var onEl = el.querySelector('#ra-order-name');
    if (onOk && onEl) {
      onOk.addEventListener('click', function() {
        var v = onEl.value.trim();
        if (!v) { onEl.focus(); return; }
        el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
        var q = el.querySelector('.ra-booking-q');
        if (q) q.textContent = '\\uD83D\\uDC64 ' + v + ' \\u2713';
        el.querySelector('.ra-booking-input-row') && el.querySelector('.ra-booking-input-row').remove();
        showOrderPhoneStep(deliveryType, tableNumber, v, deliveryAddress);
      });
      onEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') onOk.click(); });
      setTimeout(function() { onEl.focus(); }, 60);
    }
  }

  function showOrderPhoneStep(deliveryType, tableNumber, customerName, deliveryAddress) {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83D\\uDCF1 Your phone number</div>' +
      '<div class="ra-booking-input-row">' +
        '<input type="tel" class="ra-booking-input" id="ra-order-phone" placeholder="e.g. +1 555 000 0000" />' +
        '<button class="ra-chip ra-chip-primary" id="ra-op-ok">Next \\u2192</button>' +
      '</div>';
    msgList.appendChild(el);
    scrollToBottom();

    var opOk = el.querySelector('#ra-op-ok');
    var opEl = el.querySelector('#ra-order-phone');
    if (opOk && opEl) {
      opOk.addEventListener('click', function() {
        var v = opEl.value.trim();
        if (!v) { opEl.focus(); return; }
        el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
        var q = el.querySelector('.ra-booking-q'); if (q) q.textContent = '\\uD83D\\uDCF1 ' + v + ' \\u2713';
        el.querySelector('.ra-booking-input-row') && el.querySelector('.ra-booking-input-row').remove();
        showOrderEmailStep(deliveryType, tableNumber, customerName, deliveryAddress, v);
      });
      opEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') opOk.click(); });
      setTimeout(function() { opEl.focus(); }, 60);
    }
  }

  function showOrderEmailStep(deliveryType, tableNumber, customerName, deliveryAddress, phone) {
    var el = document.createElement('div');
    el.className = 'ra-booking-step';
    el.innerHTML =
      '<div class="ra-booking-q">\\uD83D\\uDCE7 Email for confirmation <span style="font-weight:400;font-size:12px;opacity:.7;">(optional)</span></div>' +
      '<div class="ra-booking-input-row">' +
        '<input type="email" class="ra-booking-input" id="ra-order-email" placeholder="you@example.com" />' +
        '<button class="ra-chip ra-chip-primary" id="ra-oe-ok">Place Order</button>' +
      '</div>' +
      '<div style="margin-top:6px;"><button class="ra-chip" id="ra-oe-skip">Skip</button></div>';
    msgList.appendChild(el);
    scrollToBottom();

    function confirmOrder(email) {
      el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
      var items = Object.values(state.cart);
      var tot = getCartTotal();
      var displaySummary = items.map(function(i) { return i.qty + '\\u00D7 ' + i.name; }).join(', ');
      var aiSummary = items.map(function(i) { return i.qty + 'x ' + i.name + ' @$' + (i.price || 0).toFixed(2); }).join(', ');
      var dtLabel = deliveryType === 'dine-in' ? 'Dine-In' : deliveryType === 'takeaway' ? 'Takeaway' : 'Delivery';
      var displayMsg = 'Place my order: ' + displaySummary;
      var name = customerName || 'Widget Customer';
      var aiMsg = 'I would like to order: ' + aiSummary + '. Total: $' + tot.toFixed(2) + '. Delivery type: ' + dtLabel + '. Customer name: ' + name + '. My phone number: ' + phone + (email ? '. Email: ' + email : '') + (tableNumber ? '. Table number: ' + tableNumber : '') + (deliveryAddress ? '. Delivery address: ' + deliveryAddress : '') + '. Please process this order now using the place_order tool.';
      state.cart = {}; updateCartBar();
      addMessage({ sender: 'customer', content: displayMsg, time: now() }, true);
      sendToAI(aiMsg);
    }

    var oeOk = el.querySelector('#ra-oe-ok');
    var oeSkip = el.querySelector('#ra-oe-skip');
    var oeEl = el.querySelector('#ra-order-email');
    if (oeOk && oeEl) {
      oeOk.addEventListener('click', function() {
        var v = oeEl.value.trim();
        confirmOrder(v);
      });
      oeEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') oeOk.click(); });
      setTimeout(function() { oeEl.focus(); }, 60);
    }
    if (oeSkip) {
      oeSkip.addEventListener('click', function() { confirmOrder(''); });
    }
  }

  /* ─── Booking flow ──────────────────────────────────── */

  function isoToTime12(isoTime) {
    var pts = isoTime.split(':'); var hh = parseInt(pts[0], 10); var mm = pts[1];
    var ap = hh >= 12 ? 'PM' : 'AM'; hh = hh % 12 || 12;
    return hh + ':' + mm + ' ' + ap;
  }

  function toIsoDate(d) {
    var y = d.getFullYear(); var m = d.getMonth() + 1; var day = d.getDate();
    return y + '-' + (m < 10 ? '0' : '') + m + '-' + (day < 10 ? '0' : '') + day;
  }

  function showBookingStep() {
    var step = state.bookingStep;
    var el = document.createElement('div');
    el.className = 'ra-booking-step';

    if (step === 0) {
      var today = new Date();
      var tom = new Date(today); tom.setDate(today.getDate() + 1);
      var da  = new Date(today); da.setDate(today.getDate() + 2);
      function fd(d) { return d.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' }); }
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDCC5 When would you like to visit?</div>' +
        '<div class="ra-chips-row" style="margin-left:0;">' +
          '<button class="ra-chip" data-val="' + escHtml(fd(today)) + '" data-iso="' + toIsoDate(today) + '">Today</button>' +
          '<button class="ra-chip" data-val="' + escHtml(fd(tom)) + '" data-iso="' + toIsoDate(tom) + '">Tomorrow</button>' +
          '<button class="ra-chip" data-val="' + escHtml(fd(da)) + '" data-iso="' + toIsoDate(da) + '">' + escHtml(da.toLocaleDateString('en-US',{weekday:'short',month:'short',day:'numeric'})) + '</button>' +
        '</div>' +
        '<div class="ra-booking-input-row">' +
          '<input type="date" class="ra-booking-input" id="ra-dp" />' +
          '<button class="ra-chip" id="ra-dp-ok">Other date</button>' +
        '</div>';
    } else if (step === 1) {
      var timeChips = [
        {label:'12:00 PM',iso:'12:00'},{label:'1:00 PM',iso:'13:00'},
        {label:'6:00 PM',iso:'18:00'},{label:'7:00 PM',iso:'19:00'},{label:'8:00 PM',iso:'20:00'}
      ];
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDD50 What time?</div>' +
        '<div class="ra-chips-row" style="margin-left:0;">' +
          timeChips.map(function(t) {
            return '<button class="ra-chip" data-val="' + t.label + '" data-iso="' + t.iso + '">' + t.label + '</button>';
          }).join('') +
        '</div>' +
        '<div class="ra-booking-input-row">' +
          '<input type="time" class="ra-booking-input" id="ra-tp" />' +
          '<button class="ra-chip" id="ra-tp-ok">Other time</button>' +
        '</div>';
    } else if (step === 2) {
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDC65 How many guests?</div>' +
        '<div class="ra-chips-row" style="margin-left:0;">' +
          ['1','2','3','4','5','6','7+'].map(function(n) {
            return '<button class="ra-chip" data-val="' + n + '">' + n + '</button>';
          }).join('') +
        '</div>';
    } else if (step === 3) {
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDC64 Name for the reservation?</div>' +
        '<div class="ra-booking-input-row">' +
          '<input type="text" class="ra-booking-input" id="ra-np" placeholder="Your name" />' +
          '<button class="ra-chip ra-chip-primary" id="ra-np-ok">Next \\u2192</button>' +
        '</div>';
    } else if (step === 4) {
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDCF1 Your phone number</div>' +
        '<div class="ra-booking-input-row">' +
          '<input type="tel" class="ra-booking-input" id="ra-bph" placeholder="e.g. +1 555 000 0000" />' +
          '<button class="ra-chip ra-chip-primary" id="ra-bph-ok">Next \\u2192</button>' +
        '</div>';
    } else if (step === 5) {
      el.innerHTML =
        '<div class="ra-booking-q">\\uD83D\\uDCE7 Email for confirmation <span style="font-weight:400;font-size:12px;opacity:.7;">(optional)</span></div>' +
        '<div class="ra-booking-input-row">' +
          '<input type="email" class="ra-booking-input" id="ra-be" placeholder="you@example.com" />' +
          '<button class="ra-chip ra-chip-primary" id="ra-be-ok">Next \\u2192</button>' +
        '</div>' +
        '<div style="margin-top:6px;"><button class="ra-chip" id="ra-be-skip">Skip</button></div>';
    } else if (step === 6) {
      var d = state.bookingData;
      el.innerHTML =
        '<div class="ra-booking-confirm">' +
          '<div class="ra-booking-title">\\uD83D\\uDCCB Confirm Reservation</div>' +
          '<div class="ra-booking-line">\\uD83D\\uDCC5 ' + escHtml(d.date || '') + '</div>' +
          '<div class="ra-booking-line">\\uD83D\\uDD50 ' + escHtml(d.time || '') + '</div>' +
          '<div class="ra-booking-line">\\uD83D\\uDC65 ' + escHtml(String(d.partySize || '')) + ' guest' + (parseInt(d.partySize, 10) !== 1 ? 's' : '') + '</div>' +
          '<div class="ra-booking-line">\\uD83D\\uDC64 ' + escHtml(d.name || '') + '</div>' +
          (d.phone ? '<div class="ra-booking-line">\\uD83D\\uDCF1 ' + escHtml(d.phone) + '</div>' : '') +
          (d.email ? '<div class="ra-booking-line">\\uD83D\\uDCE7 ' + escHtml(d.email) + '</div>' : '') +
        '</div>' +
        '<div class="ra-chips-row" style="margin-left:0;">' +
          '<button class="ra-chip ra-chip-primary" id="ra-conf">\\u2705 Confirm</button>' +
          '<button class="ra-chip" id="ra-restart">\\u2190 Start over</button>' +
        '</div>';
    }

    msgList.appendChild(el);
    scrollToBottom();

    el.querySelectorAll('.ra-chip[data-val]').forEach(function(chip) {
      chip.addEventListener('click', function() {
        handleBookingChoice(chip.getAttribute('data-val'), el, chip.getAttribute('data-iso'));
      });
    });

    if (step === 0) {
      var dpOk = el.querySelector('#ra-dp-ok'), dp = el.querySelector('#ra-dp');
      if (dpOk && dp) dpOk.addEventListener('click', function() {
        if (!dp.value) return;
        var isoDate = dp.value;
        var dt = new Date(dp.value + 'T12:00:00');
        handleBookingChoice(dt.toLocaleDateString('en-US',{weekday:'long',month:'long',day:'numeric'}), el, isoDate);
      });
    }
    if (step === 1) {
      var tpOk = el.querySelector('#ra-tp-ok'), tp = el.querySelector('#ra-tp');
      if (tpOk && tp) tpOk.addEventListener('click', function() {
        if (!tp.value) return;
        var isoTime = tp.value;
        handleBookingChoice(isoToTime12(isoTime), el, isoTime);
      });
    }
    if (step === 3) {
      var npOk = el.querySelector('#ra-np-ok'), np = el.querySelector('#ra-np');
      if (npOk && np) {
        npOk.addEventListener('click', function() { var v = np.value.trim(); if (v) handleBookingChoice(v, el); });
        np.addEventListener('keydown', function(e) { if (e.key === 'Enter') npOk.click(); });
        setTimeout(function() { np.focus(); }, 60);
      }
    }
    if (step === 4) {
      var bphOk = el.querySelector('#ra-bph-ok'), bph = el.querySelector('#ra-bph');
      if (bphOk && bph) {
        bphOk.addEventListener('click', function() {
          var v = bph.value.trim();
          if (!v) { bph.focus(); return; }
          handleBookingChoice(v, el);
        });
        bph.addEventListener('keydown', function(e) { if (e.key === 'Enter') bphOk.click(); });
        setTimeout(function() { bph.focus(); }, 60);
      }
    }
    if (step === 5) {
      var beOk = el.querySelector('#ra-be-ok'), beSkip = el.querySelector('#ra-be-skip'), beEl = el.querySelector('#ra-be');
      function advanceBookingEmail(email) {
        el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
        state.bookingData.email = email || '';
        var q5 = el.querySelector('.ra-booking-q'); if (q5) q5.textContent = '\\uD83D\\uDCE7 ' + (email ? email + ' \\u2713' : 'No email');
        var ir5 = el.querySelector('.ra-booking-input-row'); if (ir5) ir5.remove();
        var sk5 = el.querySelector('#ra-be-skip'); if (sk5) sk5.remove();
        state.bookingStep++;
        setTimeout(showBookingStep, 120);
      }
      if (beOk) beOk.addEventListener('click', function() { advanceBookingEmail(beEl ? beEl.value.trim() : ''); });
      if (beEl) beEl.addEventListener('keydown', function(e) { if (e.key === 'Enter') beOk && beOk.click(); });
      if (beSkip) beSkip.addEventListener('click', function() { advanceBookingEmail(''); });
      setTimeout(function() { if (beEl) beEl.focus(); }, 60);
    }
    if (step === 6) {
      var confBtn = el.querySelector('#ra-conf'), restBtn = el.querySelector('#ra-restart');
      if (confBtn) confBtn.addEventListener('click', function() {
        el.remove();
        var d2 = state.bookingData;
        var disp = '\\uD83D\\uDCC5 Book: ' + d2.partySize + ' guests on ' + d2.date + ' at ' + d2.time;
        var dateStr = d2.date + (d2.isoDate ? ' (ISO: ' + d2.isoDate + ')' : '');
        var timeStr = d2.time + (d2.isoTime ? ' (ISO: ' + d2.isoTime + ')' : '');
        var aiMsg = 'Please book a table for ' + d2.partySize + ' guests on ' +
          dateStr + ' at ' + timeStr +
          ' for the name ' + d2.name + '.' +
          (d2.phone ? ' Phone: ' + d2.phone + '.' : '') +
          (d2.email ? ' Email: ' + d2.email + '.' : '') +
          ' Please confirm and use the book_table tool.';
        addMessage({ sender: 'customer', content: disp, time: now() }, true);
        sendToAI(aiMsg);
        state.bookingStep = -1; state.bookingData = {};
      });
      if (restBtn) restBtn.addEventListener('click', function() {
        el.remove(); state.bookingStep = 0; state.bookingData = {}; showBookingStep();
      });
    }
  }

  function handleBookingChoice(val, el, isoVal) {
    el.querySelectorAll('button, input').forEach(function(b) { b.disabled = true; });
    var step = state.bookingStep;
    if (step === 0) {
      state.bookingData.date = val;
      if (isoVal) state.bookingData.isoDate = isoVal;
      var q = el.querySelector('.ra-booking-q'); if (q) q.textContent = '\\uD83D\\uDCC5 ' + val + ' \\u2713';
    } else if (step === 1) {
      state.bookingData.time = val;
      if (isoVal) state.bookingData.isoTime = isoVal;
      var q2 = el.querySelector('.ra-booking-q'); if (q2) q2.textContent = '\\uD83D\\uDD50 ' + val + ' \\u2713';
    } else if (step === 2) {
      state.bookingData.partySize = val;
      var q3 = el.querySelector('.ra-booking-q'); if (q3) q3.textContent = '\\uD83D\\uDC65 ' + val + ' guest' + (parseInt(val, 10) !== 1 ? 's' : '') + ' \\u2713';
    } else if (step === 3) {
      state.bookingData.name = val;
    } else if (step === 4) {
      state.bookingData.phone = val || '';
    }
    var cr = el.querySelector('.ra-chips-row'); if (cr) cr.remove();
    var ir = el.querySelector('.ra-booking-input-row'); if (ir) ir.remove();
    state.bookingStep++;
    setTimeout(showBookingStep, 120);
  }

  /* ─── Quick reply chips ─────────────────────────────── */

  function addQuickReplies(replies) {
    if (!replies || !replies.length || !msgList) return;
    var el = document.createElement('div');
    el.className = 'ra-chips-row ra-ai-chips';
    el.innerHTML = replies.map(function(r) {
      return '<button class="ra-chip">' + escHtml(r) + '</button>';
    }).join('');
    msgList.appendChild(el);

    el.querySelectorAll('.ra-chip').forEach(function(chip) {
      chip.addEventListener('click', function() {
        if (state.isLoading) return;
        var text = chip.textContent.trim();
        el.remove();
        var lower = text.toLowerCase();
        if (lower.includes('menu') || lower.includes('order food') || lower.includes('browse') || lower.includes('see our menu') || lower.includes('view menu')) {
          openMenuView();
        } else if (lower.includes('book') || lower.includes('table') || lower.includes('reserv') || lower.includes('reservation')) {
          state.bookingStep = 0; state.bookingData = {}; showBookingStep();
        } else {
          addMessage({ sender: 'customer', content: text, time: now() }, true);
          sendToAI(text);
        }
      });
    });
    scrollToBottom();
  }

  function addItemCards(items) {
    if (!items || !items.length || !msgList) return;
    var row = document.createElement('div');
    row.className = 'ra-ai-chips';
    row.style.cssText = 'display:flex;gap:8px;overflow-x:auto;padding:4px 0 4px 36px;scrollbar-width:none;';
    items.forEach(function(item) {
      var card = document.createElement('div');
      card.style.cssText = 'flex:0 0 auto;min-width:130px;max-width:160px;border:1px solid #e5e7eb;border-radius:12px;padding:10px 10px 8px;background:#fff;display:flex;flex-direction:column;gap:4px;box-shadow:0 1px 3px rgba(0,0,0,0.07);';
      var nm = document.createElement('div');
      nm.style.cssText = 'font-size:12px;font-weight:600;color:#111827;line-height:1.3;word-break:break-word;';
      nm.textContent = item.name;
      var itemPrice = isNaN(Number(item.price)) ? 0 : Number(item.price);
      var pr = document.createElement('div');
      pr.style.cssText = 'font-size:12px;color:#6b7280;font-weight:500;';
      pr.textContent = '$' + itemPrice.toFixed(2);
      var btn = document.createElement('button');
      btn.style.cssText = 'margin-top:4px;padding:4px 8px;border-radius:8px;border:none;background:' + primaryColor + ';color:#fff;font-size:11px;font-weight:600;cursor:pointer;transition:opacity 0.15s;';
      btn.textContent = '+ Add to Cart';
      btn.addEventListener('click', function() {
        var key = 'ai-' + item.name.toLowerCase().replace(/[^a-z0-9]/g,'_');
        if (!state.cart[key]) {
          state.cart[key] = { name: item.name, price: itemPrice, qty: 0 };
        }
        state.cart[key].qty++;
        updateCartBar();
        btn.textContent = '✓ Added';
        btn.style.background = '#16a34a';
        btn.disabled = true;
        setTimeout(function() {
          btn.textContent = '+ Add to Cart';
          btn.style.background = primaryColor;
          btn.disabled = false;
        }, 1500);
      });
      card.appendChild(nm);
      card.appendChild(pr);
      card.appendChild(btn);
      row.appendChild(card);
    });
    msgList.appendChild(row);
    scrollToBottom();
  }

  /* ─── Message rendering ─────────────────────────────── */

  function renderAllMessages() {
    if (!msgList) return;
    msgList.innerHTML = '';
    state.messages.forEach(function(m) { renderMessage(m); });
    scrollToBottom();
  }

  function renderMessage(msg) {
    if (!msgList) return;
    var wrap = document.createElement('div');
    wrap.className = 'ra-msg-wrap' + (msg.sender === 'customer' ? ' customer' : '');

    var icon = document.createElement('div');
    icon.className = 'ra-msg-icon ' + (msg.sender === 'customer' ? 'customer' : 'ai');
    icon.innerHTML = msg.sender === 'customer' ? 'Y' : svgBot();

    // displayText (when set) is a UI-only override so we can show a
    // condensed bubble while preserving the model's full prose in
    // msg.content for the conversation history sent on the next turn.
    var bubbleText = msg.displayText || msg.content;
    var bbl = document.createElement('div');
    bbl.innerHTML =
      '<div class="ra-bubble-msg ' + (msg.sender === 'customer' ? 'customer' : 'ai') + '">' + escHtml(bubbleText) + '</div>' +
      '<div class="ra-msg-time">' + escHtml(msg.time || '') + '</div>';

    if (msg.sender === 'customer') {
      wrap.appendChild(bbl); wrap.appendChild(icon);
    } else {
      wrap.appendChild(icon); wrap.appendChild(bbl);
    }
    msgList.appendChild(wrap);

    if (msg.orderCreated) {
      var card = document.createElement('div');
      card.className = 'ra-action-card';
      var orderLabel = msg.orderCreated.order_number ? '#' + msg.orderCreated.order_number : escHtml(String(msg.orderCreated.id || '')).slice(0, 8).toUpperCase();
      card.innerHTML = svgCheck() + ' Order placed! Order ' + orderLabel;
      msgList.appendChild(card);
    }
    if (msg.bookingCreated) {
      var card2 = document.createElement('div');
      card2.className = 'ra-action-card';
      var bookingLabel = escHtml(String(msg.bookingCreated.id || '')).slice(0, 8).toUpperCase();
      card2.innerHTML = svgCheck() + ' Booking confirmed! Ref: ' + bookingLabel;
      msgList.appendChild(card2);
    }
    if (msg.orderRejections && Array.isArray(msg.orderRejections.items) && msg.orderRejections.items.length > 0) {
      renderRejectionCard(msg.orderRejections);
    }
  }

  function renderRejectionCard(payload) {
    if (!msgList || !payload || !payload.items || !payload.items.length) return;

    var wrap = document.createElement('div');
    wrap.style.cssText = 'display:flex;gap:8px;align-items:flex-start;';

    var spacer = document.createElement('div');
    spacer.style.cssText = 'width:28px;flex-shrink:0;';
    wrap.appendChild(spacer);

    var card = document.createElement('div');
    card.className = 'ra-reject-wrap';

    var head = document.createElement('div');
    head.className = 'ra-reject-head';
    var heading = payload.items.length > 1
      ? "Some items couldn't be added"
      : "We couldn't add that item";
    head.innerHTML = svgWarn() + '<span>' + escHtml(heading) + '</span>';
    card.appendChild(head);

    var list = document.createElement('div');
    list.className = 'ra-reject-list';
    payload.items.forEach(function(item) {
      var row = document.createElement('div');
      row.className = 'ra-reject-item';

      var ic = document.createElement('div');
      ic.className = 'ra-reject-icon';
      ic.innerHTML = svgRejectIcon(item.reason);

      var body = document.createElement('div');
      body.className = 'ra-reject-body';

      var nm = document.createElement('div');
      nm.className = 'ra-reject-name';
      nm.textContent = item.name;
      body.appendChild(nm);

      var badge = document.createElement('span');
      badge.className = 'ra-reject-reason';
      badge.textContent = item.reasonLabel || 'Unavailable';
      body.appendChild(badge);

      if (item.message) {
        var detail = document.createElement('div');
        detail.className = 'ra-reject-msg';
        detail.textContent = item.message;
        body.appendChild(detail);
      }

      row.appendChild(ic);
      row.appendChild(body);
      list.appendChild(row);
    });
    card.appendChild(list);

    var actions = document.createElement('div');
    actions.className = 'ra-reject-actions';

    var menuBtn = document.createElement('button');
    menuBtn.className = 'ra-reject-btn';
    menuBtn.type = 'button';
    menuBtn.textContent = 'See menu';
    menuBtn.addEventListener('click', function() { openMenuView(); });
    actions.appendChild(menuBtn);

    var askBtn = document.createElement('button');
    askBtn.className = 'ra-reject-btn secondary';
    askBtn.type = 'button';
    askBtn.textContent = 'Suggest something';
    askBtn.addEventListener('click', function() {
      if (state.isLoading) return;
      var prompt = 'What can I order instead?';
      addMessage({ sender: 'customer', content: prompt, time: now() }, true);
      sendToAI(prompt);
    });
    actions.appendChild(askBtn);

    card.appendChild(actions);
    wrap.appendChild(card);
    msgList.appendChild(wrap);
  }

  function addMessage(msg, persist) {
    var m = Object.assign({ time: now() }, msg);
    if (persist !== false) { state.messages.push(m); saveSession(); }
    renderMessage(m);
    scrollToBottom();
  }

  function addSystemMessage(text) {
    if (!msgList) return;
    var el = document.createElement('div');
    el.className = 'ra-system-msg';
    el.textContent = text;
    msgList.appendChild(el);
    scrollToBottom();
  }

  function showTyping() {
    if (!msgList) return;
    var el = document.createElement('div');
    el.className = 'ra-msg-wrap';
    el.id = 'ra-typing-indicator';
    el.innerHTML = '<div class="ra-msg-icon ai">' + svgBot() + '</div><div class="ra-typing"><span></span><span></span><span></span></div>';
    msgList.appendChild(el);
    scrollToBottom();
  }

  function hideTyping() {
    if (!msgList) return;
    var el = msgList.querySelector('#ra-typing-indicator');
    if (el) el.remove();
  }

  function scrollToBottom() {
    if (!msgList) return;
    setTimeout(function() { msgList.scrollTop = msgList.scrollHeight; }, 30);
  }

  /* ─── Panel controls ────────────────────────────────── */

  function togglePanel() { if (state.isOpen) closePanel(); else openPanel(); }

  function openPanel() {
    state.isOpen = true;
    if (chatPanel) chatPanel.className = 'visible';
    if (badge) badge.style.display = 'none';
    bubble.innerHTML = svgClose();
    if (!state.hasStarted) startSession();
  }

  function closePanel() {
    state.isOpen = false;
    if (chatPanel) chatPanel.className = 'hidden';
    bubble.innerHTML = svgChat();
  }

  function setLoading(v) {
    state.isLoading = v;
    if (sendBtn) sendBtn.disabled = v;
    if (inputEl) inputEl.disabled = v;
  }

  /* ─── AI communication ──────────────────────────────── */

  async function sendToAI(messageText) {
    var generation = state.sessionGeneration;

    if (!state.sessionToken) { await startSession(); }
    if (generation !== state.sessionGeneration) { return; }

    if (!state.sessionToken) {
      addMessage({ sender: 'ai', content: 'Sorry, I could not connect right now. Please try again.' }, false);
      setLoading(false);
      return;
    }

    setLoading(true);
    showTyping();

    var history = state.messages.slice(-20).map(function(m) {
      return { role: m.sender === 'customer' ? 'user' : 'assistant', content: m.content };
    });

    try {
      var res = await fetch(baseUrl + '/api/widget/message', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          sessionToken: state.sessionToken,
          message: messageText,
          history: history.slice(0, -1),
        }),
      });
      var data = await res.json();

      if (generation !== state.sessionGeneration) { hideTyping(); return; }

      hideTyping();

      // Keep the model's full prose in msg.content so subsequent turns
      // re-send it as conversation history (the LLM needs the
      // item-level context for follow-ups like "why?" / "swap it").
      // When per-item rejections are present we render a condensed
      // bubble in the UI — see displayText below — but never throw
      // the original reply away.
      var rej = data.orderRejections;
      var hasRej = rej && Array.isArray(rej.items) && rej.items.length > 0;
      var fullReply = data.reply || 'How can I help you?';
      var aiMsg = {
        sender: 'ai',
        content: fullReply,
        time: now(),
        orderCreated: data.orderCreated,
        bookingCreated: data.bookingCreated,
        orderRejections: hasRej ? rej : null,
      };
      if (hasRej) {
        aiMsg.displayText = rej.items.length > 1
          ? "I couldn't add a few of those — see the details below."
          : "I couldn't add that one — see the details below.";
      }
      addMessage(aiMsg, true);

      if (data.quickReplies && data.quickReplies.length > 0) {
        setTimeout(function() { addQuickReplies(data.quickReplies); }, 80);
      }
      if (data.suggestedItems && data.suggestedItems.length > 0) {
        setTimeout(function() { addItemCards(data.suggestedItems); }, 120);
      }

      if (data.shouldEscalate) {
        addSystemMessage('You are now connected with our team. They will respond shortly.');
      }
    } catch(e) {
      if (generation !== state.sessionGeneration) { hideTyping(); return; }
      hideTyping();
      addMessage({ sender: 'ai', content: 'Sorry, something went wrong. Please try again.' }, false);
    } finally {
      if (generation === state.sessionGeneration) setLoading(false);
      if (inputEl) inputEl.focus();
    }
  }

  async function sendMessage() {
    if (!inputEl) return;
    var text = inputEl.value.trim();
    if (!text || state.isLoading) return;

    var initChips = container.querySelector('#ra-initial-chips');
    if (initChips) initChips.remove();

    inputEl.value = '';
    inputEl.style.height = 'auto';

    addMessage({ sender: 'customer', content: text, time: now() }, true);
    await sendToAI(text);
  }

  /* ─── Start Over ────────────────────────────────────── */

  function startOver() {
    state.sessionGeneration++;

    try {
      localStorage.removeItem(SESSION_KEY);
      localStorage.removeItem(HISTORY_KEY);
    } catch(e) {}

    state.sessionToken = null;
    state.conversationId = null;
    state.messages = [];
    state.hasStarted = false;
    state.cart = {};
    state.menuData = null;
    state.activeCategory = null;
    state.bookingStep = -1;
    state.bookingData = {};
    state.isLoading = false;

    if (msgList) msgList.innerHTML = '';
    if (cartBar) cartBar.style.display = 'none';
    if (badge) { badge.style.display = 'none'; badge.textContent = ''; }
    if (inputEl) {
      inputEl.value = '';
      inputEl.style.height = 'auto';
      inputEl.placeholder = (state.settings && state.settings.placeholder_text) || 'Type your message\u2026';
    }

    var wm = state.settings ? state.settings.welcome_message : '';
    if (wm) {
      setTimeout(function() {
        addMessage({ sender: 'ai', content: wm, time: now() }, false);
        setTimeout(showInitialChips, 250);
      }, 150);
    } else {
      setTimeout(showInitialChips, 150);
    }
  }

  /* ─── Session management ────────────────────────────── */

  async function startSession() {
    state.hasStarted = true;
    if (state.sessionToken) {
      if (state.messages.length === 0) {
        try {
          var hres = await fetch(baseUrl + '/api/widget/history/' + encodeURIComponent(state.sessionToken));
          if (hres.ok) {
            var hdata = await hres.json();
            if (hdata.messages && hdata.messages.length > 0) {
              state.messages = hdata.messages.map(function(m) {
                return { sender: m.sender === 'ai' || m.sender === 'assistant' ? 'ai' : 'customer', content: m.content || m.text || '', time: m.time || now() };
              });
              saveSession();
              renderAllMessages();
              return;
            }
          }
        } catch(e) {}
      }
      return;
    }
    try {
      var res = await fetch(baseUrl + '/api/widget/start', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ restaurantId: restaurantId }),
      });
      var data = await res.json();
      if (data.sessionToken) {
        state.sessionToken = data.sessionToken;
        state.conversationId = data.conversationId;
        if (data.restaurant) state.restaurantName = data.restaurant.name;
        if (data.settings) {
          state.settings = data.settings;
          primaryColor = data.settings.primary_color || primaryColor;
        }
        saveSession();
      }
    } catch(e) {
      console.error('[RestroAgent Widget] Failed to start session:', e);
    }
  }

  /* ─── Init ──────────────────────────────────────────── */

  async function init() {
    loadSession();
    try {
      var sr = await fetch(baseUrl + '/api/widget/settings?restaurantId=' + restaurantId);
      if (sr.ok) {
        var sd = await sr.json();
        if (sd && sd.settings) {
          state.settings = sd.settings;
          primaryColor = sd.settings.primary_color || '#f97316';
          botName = sd.settings.bot_name || 'AI Assistant';
          if (sd.restaurant) state.restaurantName = sd.restaurant.name;
        }
      }
    } catch(e) {}

    initShadow();

    if (state.settings && state.settings.auto_open_delay > 0) {
      setTimeout(openPanel, state.settings.auto_open_delay * 1000);
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
`;

async function getBrandingForWidget(req: Request): Promise<{ brandUrl: string; brandName: string }> {
  let brandUrl = '';
  let brandName = '';
  try {
    const { db, platformSettings } = await import('@server/db/drizzle');
    const { inArray } = await import('drizzle-orm');
    const rows = await db.select({ k: platformSettings.key, v: platformSettings.value })
      .from(platformSettings)
      .where(inArray(platformSettings.key, ['site_marketing_url', 'site_title']));
    for (const r of rows) {
      const v = typeof r.v === 'string' ? r.v : '';
      if (r.k === 'site_marketing_url' && v) brandUrl = v;
      if (r.k === 'site_title' && v) brandName = v;
    }
  } catch { /* ignore */ }
  if (!brandUrl) {
    const origin = req.headers.get('origin') || req.headers.get('referer');
    if (origin) {
      try { brandUrl = new URL(origin).origin; } catch { brandUrl = new URL(req.url).origin; }
    } else {
      brandUrl = new URL(req.url).origin;
    }
  }
  if (!brandName) brandName = 'RestroAgent';
  return { brandUrl, brandName };
}

function escapeJsString(s: string): string {
  return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/</g, '\\u003c');
}

export const GET = wrapRouteHandler(async (req: Request) => {
  const { brandUrl, brandName } = await getBrandingForWidget(req);
  const script = WIDGET_SCRIPT
    .replace(/__RA_BRAND_URL__/g, escapeJsString(brandUrl))
    .replace(/__RA_BRAND_NAME__/g, escapeJsString(brandName));
  return new Response(script, {
    headers: {
      'Content-Type': 'application/javascript; charset=utf-8',
      'Cache-Control': 'public, max-age=300',
      'Access-Control-Allow-Origin': '*',
    },
  });
});
