"use client";

import { ChangeEvent, FormEvent, useCallback, useEffect, useMemo, useState } from "react";
import QRCode from "qrcode";
import {
  BellRing,
  BedDouble,
  CalendarCheck,
  CheckCircle2,
  CircleDollarSign,
  AlertCircle,
  Eye,
  Images,
  LayoutDashboard,
  LogOut,
  LoaderCircle,
  Pencil,
  Megaphone,
  Plus,
  QrCode,
  RefreshCw,
  Search,
  Trash2,
  Upload,
  Utensils,
  Users,
  Volume2,
  X,
} from "lucide-react";
import { imageLibrary } from "../data";

type Reservation = {
  id: number;
  code: string;
  guestName: string;
  guestEmail: string | null;
  phone: string;
  roomName: string;
  checkIn: string;
  checkOut: string;
  guests: number;
  paymentMethod: string;
  notes: string | null;
  nights: number;
  totalAmount: number;
  status: string;
  adminReadAt: string | null;
  isRead: boolean;
  createdAt: string;
};

type MenuItem = {
  id: number;
  name: string;
  description: string;
  price: string;
  isAvailable: boolean;
};

type MenuCategory = {
  id: number;
  category: string;
  isActive: boolean;
  items: MenuItem[];
};

type RestaurantTable = {
  id: number;
  tableNumber: string;
  tableType: string;
  qrToken: string;
  capacity: number;
  locationNote: string | null;
  isActive: boolean;
};

type WaiterCall = {
  id: number;
  tableId: number;
  tableNumber: string;
  tableType: string;
  locationNote: string | null;
  status: "Calling" | "Acknowledged" | "Resolved";
  message: string | null;
  createdAt: string;
};

type AdminRoom = {
  databaseId: number;
  id: string;
  title: string;
  type: string;
  guests: number;
  beds: string;
  baths: number;
  price: number;
  status: string;
  image: string;
  galleryImages: string[];
  description: string;
  amenities: string[];
  isActive: boolean;
};

type PopupSettings = {
  enabled: boolean;
  images: PopupImage[];
  imageUrl: string;
  altText: string;
  linkUrl: string;
};

type PopupImage = {
  imageUrl: string;
  altText: string;
  linkUrl: string;
};

async function api<T>(url: string, options?: RequestInit): Promise<T> {
  const response = await fetch(url, {
    ...options,
    headers: { "Content-Type": "application/json", ...(options?.headers ?? {}) },
  });
  const data = await readJson(response);
  if (!response.ok) throw new Error(data.error ?? "Request failed.");
  return data;
}

// The live host can answer with an empty or HTML body (e.g. 413/502), so never assume JSON.
async function readJson(response: Response) {
  const text = await response.text();
  try {
    return text ? JSON.parse(text) : {};
  } catch {
    if (response.status === 413) return { error: "Image is too large for the server. Please use a smaller image." };
    return { error: `Server error (${response.status}). Please try again.` };
  }
}

async function uploadFile(file: File, purpose?: string): Promise<string> {
  const body = new FormData();
  body.append("file", file);
  if (purpose) body.append("purpose", purpose);
  const response = await fetch("/api/uploads", { method: "POST", body });
  const data = await readJson(response);
  if (!response.ok || !data.url) {
    throw new Error(data.error ?? (response.status === 413 ? "Image is too large for the server." : `Upload failed (${response.status}).`));
  }
  return data.url;
}

export default function AdminPage() {
  const [authenticated, setAuthenticated] = useState<boolean | null>(null);
  const [password, setPassword] = useState("");
  const [loginError, setLoginError] = useState("");
  const [tab, setTab] = useState<"overview" | "bookings" | "rooms" | "tables" | "menu" | "popup">("overview");
  const [reservations, setReservations] = useState<Reservation[]>([]);
  const [categories, setCategories] = useState<MenuCategory[]>([]);
  const [tables, setTables] = useState<RestaurantTable[]>([]);
  const [waiterCalls, setWaiterCalls] = useState<WaiterCall[]>([]);
  const [rooms, setRooms] = useState<AdminRoom[]>([]);
  const [roomEditor, setRoomEditor] = useState<AdminRoom | "new" | null>(null);
  const [popupSettings, setPopupSettings] = useState<PopupSettings>({
    enabled: false,
    images: [],
    imageUrl: "",
    altText: "Bass Resort promotion",
    linkUrl: "",
  });
  const [waiterEnabled, setWaiterEnabled] = useState(true);
  const [soundEnabled, setSoundEnabled] = useState(false);
  const [query, setQuery] = useState("");
  const [message, setMessage] = useState("");
  const [loading, setLoading] = useState(false);
  const [actionLabel, setActionLabel] = useState("");
  const [notice, setNotice] = useState<{ id: number; type: "success" | "error"; message: string } | null>(null);
  const [notificationCounts, setNotificationCounts] = useState({
    unreadReservations: 0,
    urgentWaiterCalls: 0,
  });
  const [statusFilter, setStatusFilter] = useState("All");
  const [readFilter, setReadFilter] = useState("All");
  const [dateFrom, setDateFrom] = useState("");
  const [dateTo, setDateTo] = useState("");
  const [selectedReservation, setSelectedReservation] = useState<Reservation | null>(null);

  async function runAction(loadingLabel: string, successMessage: string, action: () => Promise<void>) {
    const noticeId = Date.now();
    setActionLabel(loadingLabel);
    setNotice(null);
    try {
      await action();
      setNotice({ id: noticeId, type: "success", message: successMessage });
      window.setTimeout(() => setNotice((current) => current?.id === noticeId ? null : current), 4000);
      return true;
    } catch (error) {
      setNotice({
        id: noticeId,
        type: "error",
        message: error instanceof Error ? error.message : "Something went wrong. Please try again.",
      });
      return false;
    } finally {
      setActionLabel("");
    }
  }

  const loadData = useCallback(async () => {
    setLoading(true);
    setMessage("");
    try {
      const [reservationData, menuData, tableData, callData, roomData, waiterSetting, popupData, notifications] = await Promise.all([
        api<{ reservations: Reservation[] }>("/api/reservations"),
        api<{ categories: MenuCategory[] }>("/api/menu?admin=1"),
        api<{ tables: RestaurantTable[] }>("/api/tables"),
        api<{ calls: WaiterCall[] }>("/api/waiter-calls"),
        api<{ rooms: AdminRoom[] }>("/api/rooms?admin=1"),
        api<{ enabled: boolean }>("/api/settings/waiter-call"),
        api<PopupSettings>("/api/settings/popup"),
        api<{ unreadReservations: number; urgentWaiterCalls: number }>("/api/admin/notifications"),
      ]);
      setReservations(reservationData.reservations);
      setCategories(menuData.categories);
      setTables(tableData.tables);
      setWaiterCalls(callData.calls);
      setRooms(roomData.rooms);
      setWaiterEnabled(waiterSetting.enabled);
      setPopupSettings(popupData);
      setNotificationCounts(notifications);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "Unable to load admin data.");
    } finally {
      setLoading(false);
    }
  }, []);

  const playSiren = useCallback(() => {
    if (!soundEnabled) return;
    const AudioContextClass =
      window.AudioContext ||
      (window as typeof window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
    if (!AudioContextClass) return;
    const context = new AudioContextClass();
    const oscillator = context.createOscillator();
    const gain = context.createGain();
    oscillator.type = "square";
    oscillator.frequency.setValueAtTime(720, context.currentTime);
    oscillator.frequency.linearRampToValueAtTime(1040, context.currentTime + 0.35);
    oscillator.frequency.linearRampToValueAtTime(720, context.currentTime + 0.7);
    gain.gain.setValueAtTime(0.0001, context.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.16, context.currentTime + 0.03);
    gain.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 0.9);
    oscillator.connect(gain);
    gain.connect(context.destination);
    oscillator.start();
    oscillator.stop(context.currentTime + 0.9);
    oscillator.addEventListener("ended", () => void context.close());
  }, [soundEnabled]);

  const loadWaiterCalls = useCallback(async () => {
    try {
      const data = await api<{ calls: WaiterCall[] }>("/api/waiter-calls");
      setWaiterCalls(data.calls);
      setNotificationCounts((current) => ({
        ...current,
        urgentWaiterCalls: data.calls.filter((call) => call.status === "Calling").length,
      }));
      if (data.calls.some((call) => call.status === "Calling")) playSiren();
    } catch {
      // Keep the dashboard usable during a temporary polling failure.
    }
  }, [playSiren]);

  const loadNotificationCounts = useCallback(async () => {
    try {
      const counts = await api<{ unreadReservations: number; urgentWaiterCalls: number }>(
        "/api/admin/notifications"
      );
      setNotificationCounts(counts);
    } catch {
      // Keep the last known counts during a temporary polling failure.
    }
  }, []);

  useEffect(() => {
    api<{ authenticated: boolean }>("/api/admin/session")
      .then((data) => {
        setAuthenticated(data.authenticated);
        if (data.authenticated) void loadData();
      })
      .catch(() => setAuthenticated(false));
  }, [loadData]);

  useEffect(() => {
    if (!roomEditor) return;
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setRoomEditor(null);
    };
    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", closeOnEscape);
    return () => {
      document.body.style.overflow = "";
      window.removeEventListener("keydown", closeOnEscape);
    };
  }, [roomEditor]);

  useEffect(() => {
    if (!authenticated) return;
    const timer = window.setInterval(() => void loadWaiterCalls(), 4000);
    const notificationTimer = window.setInterval(() => void loadNotificationCounts(), 5000);
    return () => {
      window.clearInterval(timer);
      window.clearInterval(notificationTimer);
    };
  }, [authenticated, loadNotificationCounts, loadWaiterCalls]);

  const filteredReservations = reservations.filter((reservation) => {
    const matchesSearch = `${reservation.code} ${reservation.guestName} ${reservation.roomName} ${reservation.phone}`
      .toLowerCase()
      .includes(query.toLowerCase());
    const matchesStatus = statusFilter === "All" || reservation.status === statusFilter;
    const matchesRead =
      readFilter === "All" ||
      (readFilter === "Unread" ? !reservation.isRead : reservation.isRead);
    const matchesFrom = !dateFrom || reservation.checkIn >= dateFrom;
    const matchesTo = !dateTo || reservation.checkIn <= dateTo;
    return matchesSearch && matchesStatus && matchesRead && matchesFrom && matchesTo;
  });

  const pending = reservations.filter((reservation) => reservation.status === "Pending").length;
  const confirmed = reservations.filter((reservation) =>
    ["Confirmed", "Checked In"].includes(reservation.status)
  ).length;
  const expectedRevenue = useMemo(
    () =>
      reservations
        .filter((reservation) => reservation.status !== "Cancelled")
        .reduce((sum, reservation) => sum + reservation.totalAmount, 0),
    [reservations]
  );
  const activeCalls = waiterCalls.filter((call) => call.status !== "Resolved");
  const urgentCalls = waiterCalls.filter((call) => call.status === "Calling");

  async function login(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLoginError("");
    try {
      await api("/api/admin/login", { method: "POST", body: JSON.stringify({ password }) });
      setAuthenticated(true);
      setPassword("");
      await loadData();
    } catch (error) {
      setLoginError(error instanceof Error ? error.message : "Login failed.");
    }
  }

  async function logout() {
    await api("/api/admin/logout", { method: "POST" });
    setAuthenticated(false);
    setReservations([]);
    setCategories([]);
  }

  async function updateReservation(id: number, status: string) {
    await runAction("Updating reservation...", "Reservation updated successfully.", async () => {
      await api(`/api/reservations/${id}`, {
        method: "PATCH",
        body: JSON.stringify({ status, markRead: true }),
      });
      setReservations((current) =>
        current.map((reservation) =>
          reservation.id === id
            ? { ...reservation, status, isRead: true, adminReadAt: reservation.adminReadAt ?? new Date().toISOString() }
            : reservation
        )
      );
      setNotificationCounts((current) => ({
        ...current,
        unreadReservations: reservations.find((reservation) => reservation.id === id && !reservation.isRead)
          ? Math.max(0, current.unreadReservations - 1)
          : current.unreadReservations,
      }));
    });
  }

  async function viewReservation(reservation: Reservation) {
    if (!reservation.isRead) {
      await api(`/api/reservations/${reservation.id}`, {
        method: "PATCH",
        body: JSON.stringify({ markRead: true }),
      });
      const updated = { ...reservation, isRead: true, adminReadAt: new Date().toISOString() };
      setReservations((current) => current.map((item) => (item.id === reservation.id ? updated : item)));
      setSelectedReservation(updated);
      setNotificationCounts((current) => ({
        ...current,
        unreadReservations: Math.max(0, current.unreadReservations - 1),
      }));
    } else {
      setSelectedReservation(reservation);
    }
  }

  async function markAllReservationsRead() {
    await runAction("Marking reservations as read...", "All reservations marked as read.", async () => {
      await api<{ markedRead: number }>("/api/reservations/read", { method: "POST" });
      setReservations((current) =>
        current.map((reservation) => ({
          ...reservation,
          isRead: true,
          adminReadAt: reservation.adminReadAt ?? new Date().toISOString(),
        }))
      );
      setNotificationCounts((current) => ({ ...current, unreadReservations: 0 }));
    });
  }

  async function updateWaiterCall(id: number, status: "Acknowledged" | "Resolved") {
    await runAction("Updating waiter call...", "Waiter call updated successfully.", async () => {
      await api(`/api/waiter-calls/${id}`, {
        method: "PATCH",
        body: JSON.stringify({ status }),
      });
      await loadWaiterCalls();
    });
  }

  async function toggleWaiterCalling() {
    const next = !waiterEnabled;
    await runAction("Updating waiter-call service...", "Waiter-call setting saved successfully.", async () => {
      const result = await api<{ enabled: boolean }>("/api/settings/waiter-call", {
        method: "PATCH",
        body: JSON.stringify({ enabled: next }),
      });
      setWaiterEnabled(result.enabled);
    });
  }

  async function savePopup(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction("Saving popup settings...", "Popup settings saved successfully.", async () => {
      const data = new FormData(form);
      const result = await api<PopupSettings>("/api/settings/popup", {
        method: "PATCH",
        body: JSON.stringify({
          enabled: data.get("enabled") === "on",
          images: popupSettings.images,
          imageUrl: popupSettings.images[0]?.imageUrl ?? "",
          altText: popupSettings.images[0]?.altText ?? "Bass Resort promotion",
          linkUrl: popupSettings.images[0]?.linkUrl ?? "",
        }),
      });
      setPopupSettings(result);
    });
  }

  function roomPayload(form: HTMLFormElement) {
    const data = new FormData(form);
    return {
      roomCode: data.get("roomCode"),
      title: data.get("title"),
      type: data.get("type"),
      guests: Number(data.get("guests")),
      beds: data.get("beds"),
      baths: Number(data.get("baths")),
      price: Number(data.get("price")),
      status: data.get("status"),
      image: data.get("image"),
      galleryImages: data.get("galleryImages"),
      description: data.get("description"),
      amenities: String(data.get("amenities") ?? ""),
      isActive: data.get("isActive") === "on",
    };
  }

  async function addRoom(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    const created = await runAction("Creating room...", "Room created successfully.", async () => {
      await api("/api/rooms", { method: "POST", body: JSON.stringify(roomPayload(form)) });
      await loadData();
    });
    if (created) setRoomEditor(null);
  }

  async function saveRoom(event: FormEvent<HTMLFormElement>, room: AdminRoom) {
    event.preventDefault();
    const form = event.currentTarget;
    const saved = await runAction(`Saving ${room.title}...`, "Room saved successfully.", async () => {
      await api(`/api/rooms/${room.databaseId}`, {
        method: "PATCH",
        body: JSON.stringify(roomPayload(form)),
      });
      await loadData();
    });
    if (saved) setRoomEditor(null);
  }

  async function deleteRoom(id: number) {
    if (!window.confirm("Delete this room from the website and reservation inventory?")) return;
    const deleted = await runAction("Deleting room...", "Room deleted successfully.", async () => {
      await api(`/api/rooms/${id}`, { method: "DELETE" });
      await loadData();
    });
    if (deleted) setRoomEditor(null);
  }

  async function addTable(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction("Creating table and QR...", "Table created successfully.", async () => {
      const data = new FormData(form);
      await api("/api/tables", {
        method: "POST",
        body: JSON.stringify({
          tableNumber: data.get("tableNumber"),
          tableType: data.get("tableType"),
          capacity: Number(data.get("capacity")),
          locationNote: data.get("locationNote"),
        }),
      });
      form.reset();
      await loadData();
    });
  }

  async function saveTable(event: FormEvent<HTMLFormElement>, table: RestaurantTable) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction(`Saving table ${table.tableNumber}...`, "Table saved successfully.", async () => {
      const data = new FormData(form);
      await api(`/api/tables/${table.id}`, {
        method: "PATCH",
        body: JSON.stringify({
          tableNumber: data.get("tableNumber"),
          tableType: data.get("tableType"),
          capacity: Number(data.get("capacity")),
          locationNote: data.get("locationNote"),
          isActive: data.get("isActive") === "on",
        }),
      });
      await loadData();
    });
  }

  async function deleteTable(id: number) {
    if (!window.confirm("Delete this table, its QR, and waiter-call history?")) return;
    await runAction("Deleting table...", "Table deleted successfully.", async () => {
      await api(`/api/tables/${id}`, { method: "DELETE" });
      await loadData();
    });
  }

  async function addCategory(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction("Adding menu category...", "Category added successfully.", async () => {
      const data = new FormData(form);
      await api("/api/menu/categories", {
        method: "POST",
        body: JSON.stringify({ name: data.get("name") }),
      });
      form.reset();
      await loadData();
    });
  }

  async function saveCategory(event: FormEvent<HTMLFormElement>, category: MenuCategory) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction(`Saving ${category.category}...`, "Category saved successfully.", async () => {
      const data = new FormData(form);
      await api(`/api/menu/categories/${category.id}`, {
        method: "PATCH",
        body: JSON.stringify({
          name: data.get("name"),
          isActive: data.get("isActive") === "on",
        }),
      });
      await loadData();
    });
  }

  async function deleteCategory(id: number) {
    if (!window.confirm("Delete this category and every item inside it?")) return;
    await runAction("Deleting category...", "Category deleted successfully.", async () => {
      await api(`/api/menu/categories/${id}`, { method: "DELETE" });
      await loadData();
    });
  }

  async function addItem(event: FormEvent<HTMLFormElement>, categoryId: number) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction("Adding menu item...", "Menu item added successfully.", async () => {
      const data = new FormData(form);
      await api("/api/menu/items", {
        method: "POST",
        body: JSON.stringify({
          categoryId,
          name: data.get("name"),
          description: data.get("description"),
          price: data.get("price"),
        }),
      });
      form.reset();
      await loadData();
    });
  }

  async function saveItem(event: FormEvent<HTMLFormElement>, item: MenuItem, categoryId: number) {
    event.preventDefault();
    const form = event.currentTarget;
    await runAction(`Saving ${item.name}...`, "Menu item saved successfully.", async () => {
      const data = new FormData(form);
      await api(`/api/menu/items/${item.id}`, {
        method: "PATCH",
        body: JSON.stringify({
          categoryId: Number(data.get("categoryId") ?? categoryId),
          name: data.get("name"),
          description: data.get("description"),
          price: data.get("price"),
          isAvailable: data.get("isAvailable") === "on",
        }),
      });
      await loadData();
    });
  }

  async function deleteItem(id: number) {
    if (!window.confirm("Delete this menu item?")) return;
    await runAction("Deleting menu item...", "Menu item deleted successfully.", async () => {
      await api(`/api/menu/items/${id}`, { method: "DELETE" });
      await loadData();
    });
  }

  if (authenticated === null) {
    return <main className="admin-login-shell"><p>Loading admin panel...</p></main>;
  }

  if (!authenticated) {
    return (
      <main className="admin-login-shell">
        <form className="admin-login-card" onSubmit={login}>
          <span className="eyebrow">Bass Resort</span>
          <h1>Admin Login</h1>
          <p>Sign in to manage reservations and the live restaurant menu.</p>
          <label>
            Admin Password
            <input
              type="password"
              value={password}
              onChange={(event) => setPassword(event.target.value)}
              required
              autoFocus
            />
          </label>
          {loginError ? <p className="form-error">{loginError}</p> : null}
          <button className="submit-button" type="submit">Sign In</button>
          <a href="/">Back to Website</a>
        </form>
      </main>
    );
  }

  const tabs = [
    ["overview", LayoutDashboard, "Overview"],
    ["bookings", CalendarCheck, "Reservations"],
    ["rooms", BedDouble, "Rooms"],
    ["tables", QrCode, "Tables & QR"],
    ["menu", Utensils, "Menu Manager"],
    ["popup", Megaphone, "Popup"],
  ] as const;

  return (
    <main className={`admin-shell ${actionLabel ? "is-action-loading" : ""}`} aria-busy={Boolean(actionLabel)}>
      {actionLabel ? (
        <div className="admin-action-loader" role="status" aria-live="polite">
          <LoaderCircle size={22} />
          <span>{actionLabel}</span>
        </div>
      ) : null}
      {notice ? (
        <div className={`admin-toast ${notice.type}`} role={notice.type === "error" ? "alert" : "status"} aria-live="polite">
          {notice.type === "success" ? <CheckCircle2 size={22} /> : <AlertCircle size={22} />}
          <div>
            <strong>{notice.type === "success" ? "Saved successfully" : "Action failed"}</strong>
            <span>{notice.message}</span>
          </div>
          <button type="button" aria-label="Dismiss notification" onClick={() => setNotice(null)}><X size={16} /></button>
        </div>
      ) : null}
      <aside className="admin-sidebar">
        <a className="admin-logo" href="/" aria-label="Bass Resort home">
          <span className="logo-mark"><img src="/images/logo.png" alt="" aria-hidden="true" /></span>
        </a>
        <div className="admin-tabs">
          {tabs.map(([key, Icon, label]) => {
            const badge =
              key === "bookings"
                ? notificationCounts.unreadReservations
                : key === "tables"
                  ? notificationCounts.urgentWaiterCalls
                  : key === "overview"
                    ? notificationCounts.unreadReservations + notificationCounts.urgentWaiterCalls
                    : 0;
            return (
              <button
                className={tab === key ? "active" : ""}
                key={key}
                onClick={() => {
                  setTab(key);
                  if (key === "bookings") void loadData();
                }}
              >
                <Icon size={18} /> <span>{label}</span>
                {badge > 0 ? <b className="admin-tab-badge">{badge > 99 ? "99+" : badge}</b> : null}
              </button>
            );
          })}
        </div>
        <button className="back-site" type="button" onClick={logout}>
          <LogOut size={17} /> Sign Out
        </button>
      </aside>

      <section className="admin-main">
        <header className="admin-header">
          <div>
            <span className="eyebrow">Admin Panel</span>
            <h1>{tabs.find(([key]) => key === tab)?.[2]}</h1>
          </div>
          <div className="admin-header-actions">
            <div className="admin-search">
              <Search size={17} />
              <input
                placeholder="Search reservations..."
                value={query}
                onChange={(event) => setQuery(event.target.value)}
              />
            </div>
            <button className="admin-refresh" type="button" onClick={() => void loadData()}>
              <RefreshCw size={17} /> {loading ? "Loading" : "Refresh"}
            </button>
          </div>
        </header>

        {message ? <p className="admin-message">{message}</p> : null}

        <section className={`waiter-alert-board ${urgentCalls.length ? "has-calls" : ""}`}>
          <div className="waiter-alert-heading">
            <div>
              <BellRing size={24} />
              <span>
                <strong>{urgentCalls.length ? `${urgentCalls.length} table${urgentCalls.length > 1 ? "s" : ""} calling` : "Waiter call monitor"}</strong>
                {urgentCalls.length ? "Immediate service requested" : "No unacknowledged calls"}
              </span>
            </div>
            <button type="button" onClick={() => setSoundEnabled((value) => !value)}>
              <Volume2 size={17} /> Siren {soundEnabled ? "On" : "Off"}
            </button>
            <button
              className={waiterEnabled ? "service-toggle enabled" : "service-toggle"}
              type="button"
              onClick={() => void toggleWaiterCalling()}
            >
              Customer Call Waiter: {waiterEnabled ? "On" : "Off"}
            </button>
          </div>
          {activeCalls.length ? (
            <div className="waiter-call-list">
              {activeCalls.map((call) => (
                <article className={call.status === "Calling" ? "calling" : ""} key={call.id}>
                  <div>
                    <span>{call.tableType}</span>
                    <h3>Table {call.tableNumber}</h3>
                    <p>{call.locationNote || "Restaurant table"} · {new Date(call.createdAt).toLocaleTimeString()}</p>
                  </div>
                  <div>
                    {call.status === "Calling" ? (
                      <button type="button" onClick={() => void updateWaiterCall(call.id, "Acknowledged")}>
                        Acknowledge
                      </button>
                    ) : null}
                    <button className="resolve" type="button" onClick={() => void updateWaiterCall(call.id, "Resolved")}>
                      Resolved
                    </button>
                  </div>
                </article>
              ))}
            </div>
          ) : null}
        </section>

        {tab === "overview" ? (
          <>
            <div className="kpi-grid">
              <Kpi icon={<CalendarCheck />} label="Reservations" value={reservations.length} />
              <Kpi icon={<Users />} label="Pending" value={pending} />
              <Kpi icon={<LayoutDashboard />} label="Active" value={confirmed} />
              <Kpi icon={<CircleDollarSign />} label="Expected" value={`NPR ${expectedRevenue.toLocaleString()}`} />
            </div>
            <div className="admin-grid">
              <Panel title="Latest Reservations">
                <div className="timeline">
                  {reservations.slice(0, 8).map((reservation) => (
                    <p key={reservation.id}>
                      <strong>{reservation.guestName}</strong>
                      <span>{reservation.roomName} · {reservation.status}</span>
                    </p>
                  ))}
                  {!reservations.length ? <p>No reservations yet.</p> : null}
                </div>
              </Panel>
              <Panel title="Live Menu">
                <div className="billing-watch">
                  <strong>{categories.reduce((sum, category) => sum + category.items.length, 0)}</strong>
                  <p>items across {categories.length} categories.</p>
                </div>
              </Panel>
            </div>
          </>
        ) : null}

        {tab === "rooms" ? (
          <div className="room-manager">
            <div className="room-manager-toolbar">
              <p>
                <strong>{rooms.length} rooms</strong>
                {rooms.filter((room) => room.isActive).length} visible on the website
              </p>
              <button className="admin-refresh" type="button" onClick={() => setRoomEditor("new")}>
                <Plus size={17} /> Add Room
              </button>
            </div>
            <div className="room-tile-grid">
              {rooms.map((room) => (
                <article className={`room-tile ${room.isActive ? "" : "is-hidden"}`} key={room.databaseId}>
                  <div className="room-tile-media">
                    <img src={room.image} alt={room.title} loading="lazy" />
                    <span className="room-tile-status">{room.status}</span>
                    {room.isActive ? null : <span className="room-tile-hidden">Hidden</span>}
                  </div>
                  <div className="room-tile-body">
                    <small>{room.id} · {room.type}</small>
                    <h3>{room.title}</h3>
                    <p className="room-tile-meta">
                      <span><Users size={14} /> {room.guests} guests</span>
                      <span><BedDouble size={14} /> {room.beds}</span>
                      <span><Images size={14} /> {room.galleryImages.length} photos</span>
                    </p>
                    <div className="room-tile-footer">
                      <strong>NPR {room.price.toLocaleString()}<small> / night</small></strong>
                      <button className="room-tile-edit" type="button" onClick={() => setRoomEditor(room)}>
                        <Pencil size={15} /> Edit
                      </button>
                    </div>
                  </div>
                </article>
              ))}
            </div>
            {!rooms.length && !loading ? <p className="empty-state">No rooms yet. Add your first room.</p> : null}
          </div>
        ) : null}

        {roomEditor ? (
          <div className="room-editor-backdrop">
            <aside className="room-editor" role="dialog" aria-modal="true" aria-labelledby="room-editor-title">
              <header>
                <div>
                  <span className="eyebrow">{roomEditor === "new" ? "New room" : roomEditor.id}</span>
                  <h2 id="room-editor-title">{roomEditor === "new" ? "Add Room" : roomEditor.title}</h2>
                </div>
                <button className="room-editor-close" type="button" aria-label="Close editor" onClick={() => setRoomEditor(null)}>
                  <X size={20} />
                </button>
              </header>
              {roomEditor === "new" ? (
                <RoomForm onSubmit={addRoom} imageOptions={imageLibrary} submitLabel="Add Room" />
              ) : (
                <>
                  <RoomForm
                    key={roomEditor.databaseId}
                    room={roomEditor}
                    imageOptions={imageLibrary}
                    submitLabel="Save Changes"
                    onSubmit={(event) => void saveRoom(event, roomEditor)}
                  />
                  <button className="danger-button room-delete-button" type="button" onClick={() => void deleteRoom(roomEditor.databaseId)}>
                    <Trash2 size={16} /> Delete Room
                  </button>
                </>
              )}
            </aside>
          </div>
        ) : null}

        {tab === "tables" ? (
          <div className="table-admin">
            <Panel title="Add Restaurant Table">
              <form className="table-add-form" onSubmit={addTable}>
                <input name="tableNumber" placeholder="Table number, e.g. 01" required />
                <input name="tableType" placeholder="Type, e.g. Garden / Terrace" required />
                <input name="capacity" type="number" min="1" max="50" defaultValue="4" required />
                <input name="locationNote" placeholder="Location note (optional)" />
                <button className="submit-button" type="submit"><Plus size={17} /> Create Table & QR</button>
              </form>
            </Panel>
            <div className="table-admin-grid">
              {tables.map((table) => (
                <TableManagerCard
                  key={table.id}
                  table={table}
                  onSave={saveTable}
                  onDelete={deleteTable}
                />
              ))}
            </div>
          </div>
        ) : null}

        {tab === "popup" ? (
          <div className="popup-admin">
            <Panel title="Website Popup">
              <form className="popup-manager-form" onSubmit={savePopup}>
                <label className="admin-check popup-toggle">
                  <input name="enabled" type="checkbox" defaultChecked={popupSettings.enabled} /> Show popup on website
                </label>
                <PopupImageUpload
                  images={popupSettings.images}
                  onChange={(images) =>
                    setPopupSettings((current) => ({
                      ...current,
                      images,
                      imageUrl: images[0]?.imageUrl ?? "",
                      altText: images[0]?.altText ?? current.altText,
                      linkUrl: images[0]?.linkUrl ?? "",
                    }))
                  }
                />
                <button className="submit-button" type="submit">
                  Save Popup
                </button>
              </form>
            </Panel>
          </div>
        ) : null}

        {tab === "bookings" ? (
          <Panel title="Reservation Control" className="reservation-control-panel">
            <div className="reservation-toolbar">
              <select value={statusFilter} onChange={(event) => setStatusFilter(event.target.value)}>
                <option>All</option>
                <option>Pending</option>
                <option>Confirmed</option>
                <option>Checked In</option>
                <option>Checked Out</option>
                <option>Cancelled</option>
              </select>
              <select value={readFilter} onChange={(event) => setReadFilter(event.target.value)}>
                <option>All</option>
                <option>Unread</option>
                <option>Read</option>
              </select>
              <label>
                Arrival from
                <input type="date" value={dateFrom} onChange={(event) => setDateFrom(event.target.value)} />
              </label>
              <label>
                Arrival to
                <input type="date" value={dateTo} onChange={(event) => setDateTo(event.target.value)} />
              </label>
              <button
                type="button"
                onClick={() => {
                  setStatusFilter("All");
                  setReadFilter("All");
                  setDateFrom("");
                  setDateTo("");
                  setQuery("");
                }}
              >
                Clear Filters
              </button>
              <button className="mark-read-button" type="button" onClick={() => void markAllReservationsRead()}>
                Mark all read
              </button>
            </div>
            <p className="reservation-results">
              Showing {filteredReservations.length} of {reservations.length} reservations
              {notificationCounts.unreadReservations
                ? ` · ${notificationCounts.unreadReservations} unread`
                : " · all read"}
            </p>
            <div className="table-wrap">
              <table className="reservation-table">
                <thead>
                  <tr>
                    <th>Reference</th>
                    <th>Guest</th>
                    <th>Contact</th>
                    <th>Room</th>
                    <th>Dates</th>
                    <th>Total</th>
                    <th>Status</th>
                    <th>Details</th>
                  </tr>
                </thead>
                <tbody>
                  {filteredReservations.map((reservation) => (
                    <tr className={!reservation.isRead ? "reservation-unread" : ""} key={reservation.id}>
                      <td data-label="Reference">
                        {!reservation.isRead ? <i className="unread-dot" aria-label="Unread reservation" /> : null}
                        {reservation.code}
                      </td>
                      <td data-label="Guest">{reservation.guestName}<br /><small>{reservation.guests} guests</small></td>
                      <td data-label="Contact">{reservation.phone}<br /><small>{reservation.guestEmail || "No email"}</small></td>
                      <td data-label="Room">{reservation.roomName}</td>
                      <td data-label="Dates">{reservation.checkIn}<br />to {reservation.checkOut}</td>
                      <td data-label="Total">NPR {reservation.totalAmount.toLocaleString()}</td>
                      <td data-label="Status">
                        <select
                          value={reservation.status}
                          onChange={(event) => void updateReservation(reservation.id, event.target.value)}
                        >
                          <option>Pending</option>
                          <option>Confirmed</option>
                          <option>Checked In</option>
                          <option>Checked Out</option>
                          <option>Cancelled</option>
                        </select>
                      </td>
                      <td data-label="Details">
                        <button
                          className="view-details-button"
                          type="button"
                          onClick={() => void viewReservation(reservation)}
                        >
                          <Eye size={15} /> View Details
                        </button>
                      </td>
                    </tr>
                  ))}
                  {!filteredReservations.length ? (
                    <tr>
                      <td colSpan={8}>No reservations match these filters.</td>
                    </tr>
                  ) : null}
                </tbody>
              </table>
            </div>
          </Panel>
        ) : null}

        {tab === "menu" ? (
          <div className="menu-admin">
            <Panel title="Add Category">
              <form className="admin-inline-form" onSubmit={addCategory}>
                <input name="name" placeholder="Category name" required />
                <button className="submit-button" type="submit"><Plus size={17} /> Add Category</button>
              </form>
            </Panel>

            <div className="menu-admin-categories">
              {categories.map((category) => (
                <section className="admin-panel menu-admin-category" key={category.id}>
                  <form className="menu-category-head" onSubmit={(event) => void saveCategory(event, category)}>
                    <input name="name" defaultValue={category.category} required />
                    <label className="admin-check">
                      <input name="isActive" type="checkbox" defaultChecked={category.isActive} /> Visible
                    </label>
                    <button type="submit">Save Category</button>
                    <button className="danger-button" type="button" onClick={() => void deleteCategory(category.id)}>
                      <Trash2 size={16} /> Delete
                    </button>
                  </form>

                  <div className="menu-admin-items">
                    {category.items.map((item) => (
                      <form
                        className="menu-admin-item"
                        key={item.id}
                        onSubmit={(event) => void saveItem(event, item, category.id)}
                      >
                        <input type="hidden" name="categoryId" value={category.id} />
                        <input name="name" defaultValue={item.name} required />
                        <input name="description" defaultValue={item.description} placeholder="Description" />
                        <input name="price" defaultValue={item.price} required />
                        <label className="admin-check">
                          <input name="isAvailable" type="checkbox" defaultChecked={item.isAvailable} /> Available
                        </label>
                        <button type="submit">Save</button>
                        <button className="danger-button" type="button" onClick={() => void deleteItem(item.id)}>
                          <Trash2 size={15} />
                        </button>
                      </form>
                    ))}
                  </div>

                  <form className="menu-add-item" onSubmit={(event) => void addItem(event, category.id)}>
                    <input name="name" placeholder="New item name" required />
                    <input name="description" placeholder="Description" />
                    <input name="price" placeholder="NPR 350" required />
                    <button type="submit"><Plus size={16} /> Add Item</button>
                  </form>
                </section>
              ))}
            </div>
          </div>
        ) : null}
      </section>

      {selectedReservation ? (
        <div className="reservation-detail-backdrop" onClick={() => setSelectedReservation(null)}>
          <section
            className="reservation-detail-panel"
            role="dialog"
            aria-modal="true"
            aria-label={`Reservation ${selectedReservation.code}`}
            onClick={(event) => event.stopPropagation()}
          >
            <header>
              <div>
                <span className="eyebrow">Reservation Details</span>
                <h2>{selectedReservation.code}</h2>
              </div>
              <button type="button" onClick={() => setSelectedReservation(null)} aria-label="Close details">
                <X />
              </button>
            </header>
            <div className="reservation-detail-status">
              <span>{selectedReservation.status}</span>
              <small>Received {new Date(selectedReservation.createdAt).toLocaleString()}</small>
            </div>
            <div className="reservation-detail-grid">
              <Detail label="Guest" value={selectedReservation.guestName} />
              <Detail label="Phone" value={selectedReservation.phone} />
              <Detail label="Email" value={selectedReservation.guestEmail || "Not provided"} />
              <Detail label="Room" value={selectedReservation.roomName} />
              <Detail label="Check in" value={selectedReservation.checkIn} />
              <Detail label="Check out" value={selectedReservation.checkOut} />
              <Detail label="Guests" value={String(selectedReservation.guests)} />
              <Detail label="Nights" value={String(selectedReservation.nights)} />
              <Detail label="Payment" value={selectedReservation.paymentMethod} />
              <Detail label="Estimated total" value={`NPR ${selectedReservation.totalAmount.toLocaleString()}`} />
            </div>
            <div className="reservation-notes">
              <span>Guest notes</span>
              <p>{selectedReservation.notes || "No additional notes."}</p>
            </div>
            <label className="reservation-detail-update">
              Update status
              <select
                value={selectedReservation.status}
                onChange={(event) => {
                  const status = event.target.value;
                  void updateReservation(selectedReservation.id, status);
                  setSelectedReservation((current) => current ? { ...current, status } : current);
                }}
              >
                <option>Pending</option>
                <option>Confirmed</option>
                <option>Checked In</option>
                <option>Checked Out</option>
                <option>Cancelled</option>
              </select>
            </label>
          </section>
        </div>
      ) : null}
    </main>
  );
}

function Detail({ label, value }: { label: string; value: string }) {
  return (
    <p>
      <span>{label}</span>
      <strong>{value}</strong>
    </p>
  );
}

function RoomForm({
  room,
  imageOptions,
  submitLabel,
  onSubmit,
}: {
  room?: AdminRoom;
  imageOptions: string[];
  submitLabel: string;
  onSubmit: (event: FormEvent<HTMLFormElement>) => void | Promise<void>;
}) {
  return (
    <form className="room-manager-form" onSubmit={onSubmit}>
      <div className="form-split">
        <label className="field">Room code<input name="roomCode" defaultValue={room?.id ?? ""} placeholder="BR-DELUXE" required /></label>
        <label className="field">Title<input name="title" defaultValue={room?.title ?? ""} placeholder="Deluxe Garden Room" required /></label>
      </div>
      <div className="form-split">
        <label className="field">Room type<input name="type" defaultValue={room?.type ?? ""} placeholder="Air Conditioned Room" required /></label>
        <label className="field">Beds<input name="beds" defaultValue={room?.beds ?? ""} placeholder="1 Queen Bed" required /></label>
      </div>
      <div className="room-number-fields">
        <label className="field">Guests<input name="guests" type="number" min="1" defaultValue={room?.guests ?? 2} required /></label>
        <label className="field">Baths<input name="baths" type="number" min="1" defaultValue={room?.baths ?? 1} required /></label>
        <label className="field">Price (NPR / night)<input name="price" type="number" min="0" defaultValue={room?.price ?? ""} required /></label>
        <label className="field">Status
          <select name="status" defaultValue={room?.status ?? "Available"}>
            <option>Available</option>
            <option>Few Left</option>
            <option>Sold Out</option>
            <option>Maintenance</option>
          </select>
        </label>
      </div>
      <RoomImageUpload
        initialValue={room?.image ?? imageOptions[0]}
        imageOptions={imageOptions}
      />
      <RoomGalleryUpload initialImages={room?.galleryImages ?? []} />
      <label className="field">Description<textarea name="description" defaultValue={room?.description ?? ""} placeholder="What makes this room special?" required /></label>
      <label className="field">Amenities<input
        name="amenities"
        defaultValue={room?.amenities.join(", ") ?? "Wi-Fi, Hot shower, Parking"}
        placeholder="Separate with commas"
      /></label>
      {room ? (
        <label className="admin-check">
          <input name="isActive" type="checkbox" defaultChecked={room.isActive} /> Visible on website
        </label>
      ) : (
        <input name="isActive" type="hidden" value="on" />
      )}
      <button className="submit-button" type="submit">{submitLabel}</button>
    </form>
  );
}

function RoomImageUpload({
  initialValue,
  imageOptions,
}: {
  initialValue: string;
  imageOptions: string[];
}) {
  const [imageUrl, setImageUrl] = useState(initialValue);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState("");

  async function uploadImage(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file) return;
    setUploading(true);
    setError("");
    try {
      setImageUrl(await uploadFile(file));
    } catch (uploadError) {
      setError(uploadError instanceof Error ? uploadError.message : "Unable to upload image.");
    } finally {
      setUploading(false);
      event.target.value = "";
    }
  }

  return (
    <div className="room-image-upload">
      <div className="room-upload-preview">
        <img src={imageUrl} alt="Selected room" />
        <label>
          <Upload size={17} />
          {uploading ? "Uploading..." : "Upload Image"}
          <input
            type="file"
            accept="image/jpeg,image/png,image/webp,image/gif"
            onChange={uploadImage}
            disabled={uploading}
          />
        </label>
      </div>
      <div className="room-image-path">
        <input
          name="image"
          value={imageUrl}
          onChange={(event) => setImageUrl(event.target.value)}
          list="room-image-options"
          placeholder="/images/room.webp or https://..."
          required
        />
        <datalist id="room-image-options">
          {imageOptions.map((image) => <option value={image} key={image} />)}
        </datalist>
        <small>Upload an image or select/paste an existing image URL.</small>
      </div>
      {error ? <p className="form-error">{error}</p> : null}
    </div>
  );
}

function RoomGalleryUpload({ initialImages }: { initialImages: string[] }) {
  const [images, setImages] = useState(initialImages);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState("");

  async function uploadImages(event: ChangeEvent<HTMLInputElement>) {
    const files = Array.from(event.target.files ?? []);
    if (!files.length) return;
    setUploading(true);
    setError("");
    try {
      const uploaded: string[] = [];
      for (const file of files) {
        uploaded.push(await uploadFile(file));
      }
      setImages((current) => [...current, ...uploaded]);
    } catch (uploadError) {
      setError(uploadError instanceof Error ? uploadError.message : "Unable to upload images.");
    } finally {
      setUploading(false);
      event.target.value = "";
    }
  }

  return (
    <div className="room-gallery-upload">
      <input type="hidden" name="galleryImages" value={images.join("\n")} />
      <div className="room-gallery-heading">
        <div><strong>Room gallery</strong><small>Add the extra images shown inside the room page.</small></div>
        <label className="secondary-button">
          <Upload size={16} /> {uploading ? "Uploading..." : "Add Images"}
          <input type="file" accept="image/jpeg,image/png,image/webp,image/gif" multiple onChange={uploadImages} disabled={uploading} />
        </label>
      </div>
      {images.length ? <div className="room-gallery-admin-grid">
        {images.map((image, index) => (
          <div key={`${image}-${index}`}>
            <img src={image} alt={`Room gallery ${index + 1}`} />
            <button type="button" onClick={() => setImages((current) => current.filter((_, itemIndex) => itemIndex !== index))}>Remove</button>
          </div>
        ))}
      </div> : <p className="empty-state">No extra room images yet.</p>}
      {error ? <p className="form-error">{error}</p> : null}
    </div>
  );
}

function PopupImageUpload({
  images,
  onChange,
}: {
  images: PopupImage[];
  onChange: (images: PopupImage[]) => void;
}) {
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState("");

  async function uploadImage(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file) return;
    setUploading(true);
    setError("");
    try {
      const url = await uploadFile(file, "popup");
      onChange([
        ...images,
        {
          imageUrl: url,
          altText: "Bass Resort promotion",
          linkUrl: "",
        },
      ]);
    } catch (uploadError) {
      setError(uploadError instanceof Error ? uploadError.message : "Unable to upload popup image.");
    } finally {
      setUploading(false);
      event.target.value = "";
    }
  }

  function updateImage(index: number, patch: Partial<PopupImage>) {
    onChange(images.map((image, currentIndex) => (currentIndex === index ? { ...image, ...patch } : image)));
  }

  function removeImage(index: number) {
    onChange(images.filter((_, currentIndex) => currentIndex !== index));
  }

  return (
    <div className="popup-image-upload">
      <div className="popup-upload-controls">
        <label className="popup-upload-button">
          <Upload size={17} />
          {uploading ? "Uploading..." : "Upload Popup Image"}
          <input
            type="file"
            accept="image/jpeg,image/png,image/webp,image/gif"
            onChange={uploadImage}
            disabled={uploading}
          />
        </label>
        <small>Any image size can be uploaded. Your 1080 x 1350 px portrait creative will display best.</small>
        {error ? <p className="form-error">{error}</p> : null}
      </div>
      <div className="popup-image-list">
        {images.map((image, index) => (
          <article className="popup-image-item" key={`${image.imageUrl}-${index}`}>
            <div className="popup-upload-preview">
              <img src={image.imageUrl} alt={image.altText || "Selected popup"} />
            </div>
            <div className="popup-image-fields">
              <label>
                Popup Image URL
                <input
                  value={image.imageUrl}
                  onChange={(event) => updateImage(index, { imageUrl: event.target.value })}
                  placeholder="/uploads/popups/promo.webp"
                  required
                />
              </label>
              <div className="form-split">
                <label>
                  Image Alt Text
                  <input
                    value={image.altText}
                    onChange={(event) => updateImage(index, { altText: event.target.value })}
                    placeholder="Bass Resort promotion"
                  />
                </label>
                <label>
                  Click Link
                  <input
                    value={image.linkUrl}
                    onChange={(event) => updateImage(index, { linkUrl: event.target.value })}
                    placeholder="/booking or https://..."
                  />
                </label>
              </div>
              <button className="danger-button popup-remove-button" type="button" onClick={() => removeImage(index)}>
                <Trash2 size={15} /> Remove Popup
              </button>
            </div>
          </article>
        ))}
        {!images.length ? <p className="empty-state">Upload one or more popup images.</p> : null}
      </div>
    </div>
  );
}

function TableManagerCard({
  table,
  onSave,
  onDelete,
}: {
  table: RestaurantTable;
  onSave: (event: FormEvent<HTMLFormElement>, table: RestaurantTable) => Promise<void>;
  onDelete: (id: number) => Promise<void>;
}) {
  const [qrUrl, setQrUrl] = useState("");
  const [tableUrl, setTableUrl] = useState("");

  useEffect(() => {
    const url = `${window.location.origin}/table/${table.qrToken}`;
    setTableUrl(url);
    QRCode.toDataURL(url, {
      width: 640,
      margin: 2,
      color: { dark: "#00462d", light: "#ffffff" },
      errorCorrectionLevel: "H",
    }).then(setQrUrl);
  }, [table.qrToken]);

  return (
    <section className="admin-panel table-manager-card">
      <div className="table-qr-preview">
        {qrUrl ? <img src={qrUrl} alt={`QR code for table ${table.tableNumber}`} /> : <span>Generating QR...</span>}
        <div>
          <span>{table.tableType}</span>
          <h2>Table {table.tableNumber}</h2>
          <p>{table.locationNote || "No location note"} · {table.capacity} guests</p>
        </div>
      </div>
      <form onSubmit={(event) => void onSave(event, table)}>
        <div className="form-split">
          <input name="tableNumber" defaultValue={table.tableNumber} required />
          <input name="tableType" defaultValue={table.tableType} required />
        </div>
        <div className="form-split">
          <input name="capacity" type="number" min="1" max="50" defaultValue={table.capacity} required />
          <input name="locationNote" defaultValue={table.locationNote ?? ""} placeholder="Location note" />
        </div>
        <label className="admin-check">
          <input name="isActive" type="checkbox" defaultChecked={table.isActive} /> QR active
        </label>
        <div className="table-card-actions">
          <button type="submit">Save Table</button>
          {qrUrl ? <a href={qrUrl} download={`bass-table-${table.tableNumber}-qr.png`}>Download QR</a> : null}
          <a href={tableUrl} target="_blank" rel="noreferrer">Open Guest Page</a>
          <button className="danger-button" type="button" onClick={() => void onDelete(table.id)}>
            <Trash2 size={15} /> Delete
          </button>
        </div>
      </form>
    </section>
  );
}

function Kpi({ icon, label, value }: { icon: React.ReactNode; label: string; value: string | number }) {
  return (
    <article className="kpi-card">
      <span>{icon}</span>
      <p>{label}</p>
      <strong>{value}</strong>
    </article>
  );
}

function Panel({
  title,
  children,
  className = "",
}: {
  title: string;
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <section className={`admin-panel ${className}`}>
      <h2>{title}</h2>
      {children}
    </section>
  );
}
