/* Main App for Seatiq */
const { useState: uS, useEffect: uE, useMemo: uM } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "granularity": 30,
  "sidebar": true
}/*EDITMODE-END*/;

// Wrap setter-from-hook to match React's setState(prev => ...) shape so
// existing components (FloorView etc.) keep working unchanged.
function legacySetter(currentDocs, ops) {
  return (updater) => {
    const next = typeof updater === "function" ? updater(currentDocs) : updater;
    ops?.replaceAll(next);
  };
}

function App() {
  const auth = window.useAuth();
  const fb = window.fb;
  const tenantId = auth?.tenantId;

  const [tables,        tablesOps,        tLoad] = useTenantCollection("tables");
  const [rooms,         roomsOps,         rLoad] = useTenantCollection("rooms");
  const [walls,         wallsOps,         wLoad] = useTenantCollection("walls");
  const [reservations,  resOps,           reLoad] = useTenantCollection("reservations");
  const [waitlist,      wlOps,            wlLoad] = useTenantCollection("waitlist");

  const setTables       = uM(() => legacySetter(tables, tablesOps), [tables, tablesOps]);
  const setRooms        = uM(() => legacySetter(rooms, roomsOps),   [rooms, roomsOps]);
  const setWalls        = uM(() => legacySetter(walls, wallsOps),   [walls, wallsOps]);
  const setReservations = uM(() => legacySetter(reservations, resOps), [reservations, resOps]);
  const setWaitlist     = uM(() => legacySetter(waitlist, wlOps),   [waitlist, wlOps]);

  const [selectedId, setSelectedId] = uS(null);
  const [date, setDate] = uS(new Date(2026, 4, 18, 19, 12));
  const [page, setPage] = uS('res');
  const [view, setView] = uS('day');
  const [filter, setFilter] = uS('Alle');
  const [showNew, setShowNew] = uS(false);
  const [showWalkin, setShowWalkin] = uS(false);
  const [showWaitlist, setShowWaitlist] = uS(false);
  const [showNotifs, setShowNotifs] = uS(false);
  const [notifications, setNotifications] = uS([
    { id: 'n1', icon: 'plus',         color: 'green',  title: 'Ny online reservation: Hans Egede', sub: '2 pers · 20:00', time: '4 min siden', unread: true },
    { id: 'n2', icon: 'clock',        color: 'yellow', title: 'Anna Vestergaard tilføjet til venteliste', sub: '2 pers · ønsker 19:30', time: '12 min siden', unread: true },
    { id: 'n3', icon: 'message',      color: 'blue',   title: 'Påmindelses-SMS sendt til 6 gæster',                 time: '18 min siden', unread: true },
    { id: 'n4', icon: 'x',            color: 'red',    title: 'Mette Andersen aflyste sin reservation',           sub: '4 pers · stod til kl 19:00',   time: '38 min siden', unread: false },
    { id: 'n5', icon: 'check-circle', color: 'green',  title: 'Familien Mortensen bekræftet via SMS',             time: '1 t siden', unread: false },
    { id: 'n6', icon: 'phone',        color: 'blue',   title: 'Karen Strøm ringede — ønsker at flytte til 19:30',   time: '2 t siden', unread: false },
    { id: 'n7', icon: 'gift',         color: 'green',  title: 'Gavekort solgt — 1.800 kr til Anna Sommer',         time: '3 t siden', unread: false },
    { id: 'n8', icon: 'star',         color: 'yellow', title: 'Ny anmeldelse fra Mikkel Holst', sub: '★★★★★ „En fantastisk aften“', time: 'I går', unread: false },
  ]);
  const unread = notifications.filter(n => n.unread).length;

  const pushNotif = (n) => setNotifications(prev => [
    { id: 'n' + Date.now() + Math.random().toString(36).slice(2,4), unread: true, time: 'Lige nu', ...n },
    ...prev
  ]);
  // Audit-log entries for the /admin activity log (non-blocking).
  const logActivity = (kind, payload = {}) => {
    if (!tenantId) return;
    fb.addDoc(fb.collection(fb.db, "tenants", tenantId, "activity"), {
      kind, ...payload, by: auth.userDoc?.email || auth.user?.email || "?",
      at: fb.serverTimestamp(),
    }).catch(() => {});
    fb.setDoc(fb.doc(fb.db, "tenants", tenantId), {
      lastActivityAt: fb.serverTimestamp(),
    }, { merge: true }).catch(() => {});
  };

  const [now, setNow] = uS(new Date(2026, 4, 18, 19, 12));

  const liveSections = uM(() => {
    return rooms.map(r => ({
      id: r.id,
      label: r.id === 'Kammer' ? 'Kammer (privat)' : (r.label || r.id).replace(/·.*$/, '').trim(),
      tableIds: tables.filter(t => t.room === r.id).map(t => t.id),
    })).filter(s => s.tableIds.length > 0);
  }, [tables, rooms]);

  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  uE(() => { document.documentElement.dataset.theme = t.theme; }, [t.theme]);

  // Auto-hide sidebar on phone-sized viewports on first load so the
  // overlay version doesn't cover content unexpectedly.
  uE(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    const mq = window.matchMedia('(max-width: 640px)');
    if (mq.matches && t.sidebar) setTweak('sidebar', false);
    // We deliberately don't re-toggle when resizing back up — once the
    // user explicitly sets it they're in charge.
  }, []);

  uE(() => {
    const i = setInterval(() => {
      setNow(prev => { const d = new Date(prev); d.setMinutes(d.getMinutes() + 1); return d; });
    }, 30000);
    return () => clearInterval(i);
  }, []);

  const visibleRes = uM(() => {
    if (filter === 'Alle') return reservations;
    if (filter === 'Frokost') return reservations.filter(r => r.start < 15 * 60);
    if (filter === 'Aften')   return reservations.filter(r => r.start >= 17 * 60);
    if (filter === 'Bar')     return reservations.filter(r => ['b1','b2','b3'].includes(r.table));
    return reservations;
  }, [reservations, filter]);

  const stats = uM(() => {
    const active = reservations.filter(r => r.status !== 'finished' && r.status !== 'blocked');
    return {
      reservations: active.length,
      covers: active.reduce((a, r) => a + r.pax, 0),
      seated: reservations.filter(r => r.status === 'seated').length,
      arriving: reservations.filter(r => r.status === 'arriving').length,
      revenue: active.reduce((a, r) => a + r.pax * 685, 0),
    };
  }, [reservations]);

  const selectedRes = reservations.find(r => r.id === selectedId);
  const selectedTable = selectedRes && tables.find(x => x.id === selectedRes.table);

  const handleMove = (id, { start, table }) => {
    const r = reservations.find(x => x.id === id);
    if (!r) return;
    const newEnd = start + (r.end - r.start);
    resOps.update(id, { start, end: newEnd, table });
  };
  const handleStatusChange = (id, status) => {
    resOps.update(id, { status });
    logActivity("reservation_status", { id, status });
  };
  const handleDelete = (id) => {
    const r = reservations.find(x => x.id === id);
    if (r) {
      pushNotif({ icon: 'x', color: 'red', title: `${r.name} aflyste sin reservation`, sub: `${r.pax} pers · stod til kl ${window.SEATIQ_HELPERS.fmtTime(r.start)}` });
      logActivity("reservation_cancelled", { name: r.name, pax: r.pax });
    }
    resOps.remove(id);
    setSelectedId(null);
  };
  const handleCreate = async (data) => {
    const newId = 'r' + Math.random().toString(36).slice(2, 7);
    await resOps.add({ id: newId, ...data, source: 'Manuel', created: 'Lige nu', email: '', tags: [], allergies: [] });
    pushNotif({ icon: 'plus', color: 'green', title: `Ny reservation: ${data.name}`, sub: `${data.pax} pers · ${window.SEATIQ_HELPERS.fmtTime(data.start)}` });
    logActivity("reservation_created", { name: data.name, pax: data.pax, start: data.start });
  };
  const handleWalkin = async (data) => {
    const newId = 'r' + Math.random().toString(36).slice(2, 7);
    const nowMin = now.getHours() * 60 + now.getMinutes();
    const start = Math.floor(nowMin / 15) * 15;
    await resOps.add({
      id: newId, ...data, start, end: start + 90, status: 'seated', source: 'Walk-in', created: 'Lige nu', email: '', tags: ['Walk-in'], allergies: []
    });
    pushNotif({ icon: 'bolt', color: 'blue', title: `Walk-in sat til bords: ${data.name}`, sub: `${data.pax} pers` });
    logActivity("walkin", { name: data.name, pax: data.pax });
  };
  const handleSeatFromWaitlist = async (w) => {
    const newId = 'r' + Math.random().toString(36).slice(2, 7);
    const candidate = tables.find(x => w.pax >= x.cap[0] && w.pax <= x.cap[1]);
    const nowMin = now.getHours() * 60 + now.getMinutes();
    await resOps.add({
      id: newId, name: w.name, phone: w.phone, email: '',
      pax: w.pax, table: candidate?.id || tables[0]?.id,
      start: Math.ceil(nowMin / 15) * 15,
      end: Math.ceil(nowMin / 15) * 15 + 90,
      status: 'seated', notes: w.notes, tags: [], source: 'Walk-in', created: 'Lige nu', allergies: []
    });
    await wlOps.remove(w.id);
    pushNotif({ icon: 'check-circle', color: 'green', title: `${w.name} sat til bords fra venteliste`, sub: `${w.pax} pers` });
    logActivity("waitlist_seated", { name: w.name, pax: w.pax });
  };

  const initialLoading = tLoad || rLoad || wLoad || reLoad || wlLoad;
  if (initialLoading && tables.length === 0 && reservations.length === 0) {
    return <LoadingScreen/>;
  }

  return (
    <div className={`app ${t.sidebar ? '' : 'no-sidebar'}`}>
      <Sidebar active={page} onChange={setPage} visible={t.sidebar} />
      <div className="main">
        <TopBar view={view} onView={setView}
          page={page}
          tenantName={auth?.tenantDoc?.name}
          userEmail={auth?.userDoc?.email}
          onSignOut={auth?.signOut}
          onMenu={() => setTweak('sidebar', !t.sidebar)}
          onWaitlist={() => setShowWaitlist(true)}
          waitlistCount={waitlist.length}
          notifications={{ unread }}
          onBell={() => setShowNotifs(v => !v)} />

        {page === 'res' && (
          <>
            <KPIStrip stats={stats}
              onNewReservation={() => setShowNew(true)}
              onWalkin={() => setShowWalkin(true)} />
            <Subbar date={date} onDate={setDate}
              filter={filter} onFilter={setFilter}
              granularity={t.granularity}
              onGran={(g) => setTweak('granularity', g)}
              view={view} />

            {view === 'day' && (
              <DayView tables={tables} sections={liveSections}
                reservations={visibleRes}
                selectedId={selectedId} onSelect={setSelectedId}
                onMove={handleMove}
                granularity={t.granularity}
                now={now} />
            )}
            {view === 'floor' && (
              <FloorView tables={tables} setTables={setTables}
                rooms={rooms} setRooms={setRooms}
                walls={walls} setWalls={setWalls}
                reservations={visibleRes}
                now={now} selectedId={selectedId} onSelect={setSelectedId} />
            )}
            {view === 'list' && (
              <ListView reservations={visibleRes} tables={tables}
                selectedId={selectedId} onSelect={setSelectedId} />
            )}
            {view === 'month' && (
              <MonthView date={date} onPickDay={(d) => { setDate(d); setView('day'); }} />
            )}
          </>
        )}

        {page === 'home' && <HomePage reservations={reservations} waitlist={waitlist} tables={tables} now={now} onJump={(v) => { setPage('res'); setView(v); }}/>}
        {page === 'guests' && <GuestsPage/>}
        {page === 'stats' && <StatsPage/>}
        {page === 'gift' && <GiftPage/>}
        {page === 'menu' && <MenuPage/>}
        {page === 'comms' && <CommsPage/>}
        {page === 'settings' && <SettingsPage goRooms={() => { setPage('res'); setView('floor'); }}/>}
      </div>

      {showNotifs && (
        <NotificationsPanel items={notifications}
          onClose={() => setShowNotifs(false)}
          onMarkAllRead={() => setNotifications(prev => prev.map(n => ({ ...n, unread: false })))}
          onJump={(n) => { setNotifications(prev => prev.map(x => x.id === n.id ? { ...x, unread: false } : x)); }} />
      )}

      {selectedRes && (
        <ReservationDrawer res={selectedRes} table={selectedTable}
          onClose={() => setSelectedId(null)}
          onStatusChange={handleStatusChange}
          onDelete={handleDelete} />
      )}

      {showWaitlist && (
        <WaitlistPanel items={waitlist}
          onClose={() => setShowWaitlist(false)}
          onSeat={(w) => { handleSeatFromWaitlist(w); setShowWaitlist(false); }} />
      )}

      {showNew && (
        <NewReservationModal onClose={() => setShowNew(false)}
          onCreate={handleCreate} tables={tables} />
      )}

      {showWalkin && (
        <WalkinModal onClose={() => setShowWalkin(false)}
          onCreate={handleWalkin} tables={tables} />
      )}

      <TweaksPanel title="Seatiq tweaks">
        <TweakSection title="Visuel">
          <TweakRadio label="Tema"
            value={t.theme}
            options={[{value:'light', label:'Lys'},{value:'dark', label:'Mørk'}]}
            onChange={(v) => setTweak('theme', v)} />
          <TweakToggle label="Sidebar" value={t.sidebar}
            onChange={(v) => setTweak('sidebar', v)} />
        </TweakSection>
        <TweakSection title="Tidslinje">
          <TweakRadio label="Granularitet"
            value={t.granularity}
            options={[{value:15,label:'15m'},{value:30,label:'30m'},{value:60,label:'60m'}]}
            onChange={(v) => setTweak('granularity', v)} />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

// Route between privacy page, public booking widget, /admin, and the
// regular restaurant dashboard. /privatlivspolitik works on any host.
function Root() {
  const host = typeof window !== "undefined" ? (window.location.hostname || "") : "";
  const path = typeof window !== "undefined" ? window.location.pathname.replace(/\/+$/,"") : "";

  if (path.endsWith("/privatlivspolitik") || path.endsWith("/privacy")) {
    return <PrivacyPage/>;
  }

  // booking.* on any TLD goes to the public widget. Anything not
  // matching the known internal domains is also treated as a custom
  // booking domain — the widget itself does the tenant lookup.
  const isKnownAdminHost =
    host === "localhost" ||
    host.startsWith("seatiq.") ||
    host.endsWith(".web.app") ||
    host.endsWith(".firebaseapp.com");
  const isBookingHost = host.startsWith("booking.") || !isKnownAdminHost;
  if (isBookingHost) {
    return <PublicBookingApp/>;
  }
  const isAdmin = path.endsWith("/admin");
  if (isAdmin) {
    return <AuthGate requireRole="admin"><AdminApp/></AuthGate>;
  }
  return <AuthGate><App/></AuthGate>;
}

// Wait for Firebase SDK module to be ready before mounting.
function mount() {
  ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
}
if (window.fb && window.fb.auth) {
  mount();
} else {
  window.addEventListener("fb-ready", mount, { once: true });
}
