// aerOS Guest v3 — production data layer. Hydrates window.G2DATA (whose mock
// values come from guest2/data.jsx) from the real Django-Ninja backend, and
// exposes window.guestApi for orders / concierge / service requests.
// Loaded AFTER guest2/data.jsx and BEFORE guest3/app.jsx.
(function () {
  const api = window.aerosApi;
  const SYM = { TRY: '₺', EUR: '€', USD: '$', GBP: '£' };
  const opt = { auth: false };
  async function safe(fn) { try { return await fn(); } catch (e) { return null; } }

  // Map a TR/EN allergen name to the guest's built-in SVG icon key (lib G2 set);
  // unmapped allergens (hardal/kereviz/kükürt/lupin) fall back to a generic icon.
  function _allergenKey(name) {
    const n = (name || '').toString().toLocaleLowerCase('tr');
    if (/glu|buğday|bugday|wheat/.test(n)) return 'gluten';
    if (/süt|sut|milk|laktoz|lactose/.test(n)) return 'milk';
    if (/yumurta|egg/.test(n)) return 'egg';
    if (/kabuk|crustace|shellfish|karides|crab/.test(n)) return 'shellfish';
    if (/yumuşak|yumusak|mollus|midye|squid/.test(n)) return 'shellfish';
    if (/balık|balik|fish/.test(n)) return 'fish';
    if (/susam|sesame/.test(n)) return 'sesame';
    if (/soya|soy/.test(n)) return 'soy';
    if (/fıstı|fisti|peanut|\bnut|fındık|findik|ceviz|badem|antep/.test(n)) return 'nuts';
    return '';
  }

  const qp = new URLSearchParams(location.search);
  // URL query wins; fall back to the values config.jsx persisted from the QR
  // deep-link so a PWA relaunch (no query string) keeps the room/mode context.
  const _ctx = function (k) {
    const v = qp.get(k);
    if (v) return v;
    try { return localStorage.getItem('aeros-guest-' + k) || ''; } catch (e) { return ''; }
  };
  const MODE = _ctx('mode') === 'restaurant' ? 'restaurant' : 'room';
  const ROOM = _ctx('room');
  const TABLE = _ctx('table');
  const OUTLET = _ctx('outlet');

  window.G2CTX = { mode: MODE, room: ROOM, table: TABLE, outlet: OUTLET ? Number(OUTLET) : null };

  window.guestApi = {
    ctx: window.G2CTX,

    async createOrder(payload) { return api.data(await api.post('/qr_menu/create-order/', payload, opt)); },
    async trackOrder(id, surname) { return api.data(await api.post('/qr_menu/track-order/', { id, surname }, opt)); },

    // Concierge (room messaging).
    async conciergeActive(room) { const d = await safe(async () => api.data(await api.post('/hotel/concierge/active/', { room_number: room }, opt))); return d ? d.thread_id : null; },
    async startConcierge(room, body, name) { return api.data(await api.post('/hotel/concierge/start/', { room_number: room, body, guest_name: name || ('Oda ' + room) }, opt)); },
    async sendConcierge(threadId, body) { return api.data(await api.post('/hotel/concierge/send/', { thread_id: Number(threadId), body }, opt)); },

    // Static page full content (sections / rich body) for the guest content screens.
    async staticPage(pageId) { return await safe(async () => api.data(await api.post('/qr_menu/get-static-page/', { page_id: Number(pageId) }, opt))); },

    // Active popup event (is_popup + within date window) — shown as a modal on home.
    async popupEvent() {
      const d = await safe(async () => api.data(await api.post('/qr_menu/get-popup-event/', {}, opt)));
      if (!d) return null;
      return { id: d.id, title: d.event_name, en: d.event_name_eng || d.event_name, info: d.event_info || '', info_en: d.event_info_eng || d.event_info || '', image: d.event_img || null, date: (d.event_start_date || '').slice(0, 10) };
    },
    async conciergeMessages(threadId) { return (await safe(async () => api.data(await api.post('/hotel/concierge/messages/', { thread_id: Number(threadId) }, opt)))) || []; },

    // Service request (call waiter / request bill / water / napkins).
    async serviceRequest(kind, note) {
      const body = { kind, note: note || null, outlet_id: window.G2CTX.outlet };
      if (window.G2CTX.mode === 'room') body.room_number = window.G2CTX.room || null;
      else body.table_number = window.G2CTX.table || null;
      return api.data(await api.post('/hotel/service/request/', body, opt));
    },

    // Product portions + modifiers + allergens on demand (detail sheet).
    async productOptions(productId) {
      const d = await safe(async () => api.data(await api.post('/qr_menu/options/get/', { menu_det_id: productId }, opt)));
      if (!d) return { portions: [], mods: [], allergens: [] };
      const portions = (d.portions || []).map((p) => ({ id: p.id, label: p.name, en: p.name, price: p.rest_price }));
      const mods = [];
      (d.modifier_groups || []).forEach((g) => (g.modifiers || []).forEach((m) => mods.push({ id: m.id, label: m.name, en: m.name, price: m.price_delta })));
      return { portions, mods, allergens: d.allergen_ids || [] };
    },

    // Spa reservation (guest -> tenant spa reservations list).
    async bookSpa(serviceId, duration, price, payload) {
      const body = { service_id: serviceId, guest_surname: payload.surname || '-', room_number: window.G2CTX.room || payload.surname || '-', reservation_time: payload.when, selected_duration: duration || null, selected_price: price || null, note: payload.note || null };
      return api.data(await api.post('/qr_menu/spa/reservations/create/', body, opt));
    },

    // Transfer/VIP request (guest -> tenant transfer reservations list).
    async requestTransfer(payload) {
      const body = {
        passenger: payload.surname || '-', tel: payload.tel || null, mail: payload.mail || null,
        route: payload.route || null, car: payload.car || '-', car_price: Number(payload.price) || 0,
        flight_no: payload.flight || '', round_trip: !!payload.round, remarks: payload.remarks || null,
      };
      return api.data(await api.post('/qr_menu/transfer/vip/create/', body, opt));
    },

    // Web Push
    async pushPublicKey() { const d = await safe(async () => api.data(await api.post('/hotel/push/public-key/', {}, opt))); return d && d.public_key; },
    async pushSubscribe(sub) {
      const k = sub.toJSON().keys || {};
      return api.data(await api.post('/hotel/push/subscribe/', { endpoint: sub.endpoint, p256dh: k.p256dh, auth: k.auth, room_number: window.G2CTX.room || null, table_number: window.G2CTX.table || null }, opt));
    },
  };

  // Push enable flow (needs a secure context: HTTPS or localhost, and on iOS the
  // app must be installed to the Home Screen first).
  function _urlB64ToUint8(b64) {
    const pad = '='.repeat((4 - b64.length % 4) % 4);
    const s = (b64 + pad).replace(/-/g, '+').replace(/_/g, '/');
    const raw = atob(s); const out = new Uint8Array(raw.length);
    for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
    return out;
  }
  window.G2PUSH = {
    supported: (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) && (typeof window !== 'undefined' && 'PushManager' in window) && (typeof Notification !== 'undefined'),
    async enable() {
      if (!this.supported) return { ok: false, reason: 'unsupported' };
      try {
        const perm = await Notification.requestPermission();
        if (perm !== 'granted') return { ok: false, reason: 'denied' };
        const reg = await navigator.serviceWorker.register('sw.js');
        const key = await window.guestApi.pushPublicKey();
        if (!key) return { ok: false, reason: 'nokey' };
        let sub = await reg.pushManager.getSubscription();
        if (!sub) sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: _urlB64ToUint8(key) });
        await window.guestApi.pushSubscribe(sub);
        try { localStorage.setItem('aeros-push-on', '1'); } catch (e) {}
        return { ok: true };
      } catch (e) { return { ok: false, reason: (location.protocol !== 'https:' && location.hostname !== 'localhost') ? 'insecure' : 'error' }; }
    },
  };

  // Brand the home-screen app (name + logo). Fire-and-forget — never blocks data hydration.
  let _manifestUrl = null;
  function applyAppIdentity(b) {
    try {
      const nm = b.name || 'aerOS Misafir';
      document.title = nm;
      const ti = document.querySelector('meta[name="apple-mobile-web-app-title"]'); if (ti) ti.setAttribute('content', nm);
      const tc = document.querySelector('meta[name="theme-color"]'); if (tc && b.primary_color) tc.setAttribute('content', b.primary_color);
      const dir = location.href.split('#')[0].split('?')[0].replace(/[^/]*$/, '');
      const buildManifest = (logo512) => {
        const apple = document.querySelector('link[rel="apple-touch-icon"]'); if (apple && (logo512 || b.logo)) apple.href = logo512 || b.logo;
        const icons = [];
        if (logo512) icons.push({ src: logo512, sizes: '512x512', type: 'image/png', purpose: 'any maskable' });
        icons.push({ src: dir + 'icon-192.png', sizes: '192x192', type: 'image/png' }, { src: dir + 'icon-512.png', sizes: '512x512', type: 'image/png' });
        const man = { name: nm, short_name: nm.slice(0, 12), start_url: location.href, scope: dir, display: 'standalone', orientation: 'portrait', background_color: '#0C0A07', theme_color: (b.primary_color || '#0C0A07'), icons };
        if (_manifestUrl) { try { URL.revokeObjectURL(_manifestUrl); } catch (e) {} }
        _manifestUrl = URL.createObjectURL(new Blob([JSON.stringify(man)], { type: 'application/manifest+json' }));
        const ml = document.querySelector('link[rel="manifest"]'); if (ml) ml.href = _manifestUrl;
      };
      if (!b.logo) { buildManifest(null); return; }
      // Square the logo to 512x512 off the critical path.
      const img = new Image();
      img.onerror = () => buildManifest(null);
      img.onload = () => {
        try {
          const cv = document.createElement('canvas'); cv.width = 512; cv.height = 512;
          const cx = cv.getContext('2d'); cx.fillStyle = '#ffffff'; cx.fillRect(0, 0, 512, 512);
          const s = Math.min(512 / img.width, 512 / img.height); const w = img.width * s, h = img.height * s;
          cx.drawImage(img, (512 - w) / 2, (512 - h) / 2, w, h); buildManifest(cv.toDataURL('image/png'));
        } catch (e) { buildManifest(null); }
      };
      img.src = b.logo;
    } catch (e) {}
  }

  // Overwrite the mock G2DATA arrays with real tenant data.
  window.G2HYDRATE = async function () {
    const D = window.G2DATA;
    const roomMode = window.G2CTX.mode === 'room';

    // Live data only — drop the prototype's sample content so nothing mock shows.
    D.PRODUCTS = []; D.OUTLETS = []; D.CATS = []; D.SPA_SERVICES = []; D.ROUTES = []; D.VEHICLES = []; D.EVENTS = []; D.PAGES = [];

    const b = await safe(async () => api.data(await api.post('/company/get-branding/', {}, opt)));
    if (b) {
      D.BRAND = Object.assign({}, D.BRAND, {
        name: b.name || D.BRAND.name, sub: b.slug || D.BRAND.sub,
        color: b.primary_color || '#E0742F', logo: b.logo || null,
        currency: SYM[b.default_currency] || '₺', menuView: b.menu_view || 'gallery',
        wifiSsid: b.wifi_ssid || D.BRAND.wifiSsid, wifiPass: b.wifi_pass || D.BRAND.wifiPass, whatsapp: b.whatsapp || '',
      });
      [D.TR, D.EN].forEach((dict) => { if (b.name) { dict.brand = b.name; } });
      // Home-screen app identity (name + logo). Runs fire-and-forget so the
      // logo image decode never blocks the menu/data fetch below.
      applyAppIdentity(b);
    }
    const accent = (b && b.primary_color) || '#E0742F';

    // Branding (above) gives the accent; the remaining lists are independent —
    // fetch them concurrently so guest startup is ~2 RTTs, not ~11.
    const post = (path) => safe(async () => api.data(await api.post(path, {}, opt)));
    await Promise.all([
      post('/qr_menu/list-allergens/').then((al) => { if (al && al.length) { const m = {}, ik = {}; al.forEach((a) => { m[a.id] = a.allergens_name; ik[a.id] = _allergenKey(a.allergens_name); }); D.ALLERGENS = m; D.ALLERGEN_ICOKEY = ik; } }),
      post('/qr_menu/list-category/').then((cats) => { if (cats && cats.length) D.CATS = cats.map((c) => ({ id: c.id, name: c.category_name, en: c.category_name_eng || c.category_name })); }),
      post('/qr_menu/outlet/list/').then((outs) => { if (outs && outs.length) D.OUTLETS = outs.map((o) => ({ id: o.id, name: o.name, type: o.outlet_type, desc: '', en: '', color: accent, image: o.image || null })); }),
      post('/qr_menu/list-menu-det/').then((prods) => { if (prods && prods.length) D.PRODUCTS = prods.map((p) => ({
        id: p.id, cat: p.menu_det_category_id, name: p.menu_det_name, en: p.menu_det_name_eng || p.menu_det_name,
        desc: p.menu_det_content || '', en_desc: p.menu_det_content_eng || p.menu_det_content || '',
        price: Number(roomMode ? p.menu_det_room_price : p.menu_det_rest_price) || 0,
        cal: p.menu_det_kcal != null ? p.menu_det_kcal : null, prep: p.menu_det_prep != null ? p.menu_det_prep : null,
        color: accent, image: p.menu_det_img || null, diet: [], allergens: p.allergen_ids || [], portions: [], mods: [],
      })); }),
      post('/qr_menu/spa/services/list/').then((spa) => { if (spa) D.SPA_SERVICES = spa.filter((s) => s.active !== false).map((s) => {
        const tiers = [];
        if (s.duration_min != null) tiers.push({ d: s.duration_min + ' dk', p: Number(s.price) || 0 });
        if (s.duration_min_2) tiers.push({ d: s.duration_min_2 + ' dk', p: Number(s.price_2) || 0 });
        if (s.duration_min_3) tiers.push({ d: s.duration_min_3 + ' dk', p: Number(s.price_3) || 0 });
        return { id: s.id, name: s.name_tr, en: s.name_en || s.name_tr, color: accent, image: s.image || null, tiers };
      }); }),
      post('/qr_menu/list-event/').then((evs) => { if (evs) D.EVENTS = evs.filter((e) => e.enabled !== false).map((e) => ({ id: e.id, title: e.event_name, en: e.event_name_eng || e.event_name, info: e.event_info || '', info_en: e.event_info_eng || e.event_info || '', date: (e.event_start_date || '').slice(0, 10), image: e.event_img || null, popup: !!e.is_popup, color: accent })); }),
      post('/qr_menu/transfer/route/list/').then((routes) => { if (routes) D.ROUTES = routes.filter((r) => r.enabled !== false).map((r) => ({ id: r.id, label: r.route_name + (r.route_to ? ' → ' + r.route_to : ''), en: r.route_name, price: Number(r.route_price) || 0 })); }),
      post('/qr_menu/transfer/car/list/').then((cars) => { if (cars) D.VEHICLES = cars.filter((c) => c.enabled !== false).map((c) => ({ id: c.id, label: c.car_name + (c.car_type ? ' · ' + c.car_type : ''), cap: c.car_capacity || 0, mult: 1 })); }),
      post('/qr_menu/list-static-page/').then((pages) => { if (pages) D.PAGES = pages.filter((p) => p.enabled !== false && p.show_in_sidebar !== false).map((p) => ({ id: p.id, key: p.page_key, title: p.page_name, title_en: p.page_name_eng, icon: p.page_icon || p.page_key })); }),
    ]);

    return true;
  };
})();
