"use client";

import { useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useLocale, useTranslations } from "next-intl";
import { useIsRtl } from "@/lib/use-is-rtl";
import { Box, Pencil, Plus, Search, Trash2, Video, X } from "lucide-react";
import { DemoDataBanner } from "@/components/demo/demo-data-banner";
import { Menu3dUpload } from "@/components/media/menu-3d-upload";
import { MenuAi3dGenerate } from "@/components/media/menu-ai-3d-generate";
import { CategoryVisual } from "@/components/menu/category-visual";
import { CategoryMediaFields } from "@/components/menu/category-media-fields";
import type { CategoryIconSelection } from "@/components/menu/category-preset-picker";
import { DEFAULT_CATEGORY_ICON_STYLE } from "@/lib/category-icon-presets";
import { apiDelete, apiGet, apiPatch, apiPost } from "@/lib/api/client";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { notify } from "@/lib/notify";
import { useApiError } from "@/lib/use-api-error";
import { useAuthStore } from "@/lib/stores/auth.store";
import { useBranchStore } from "@/lib/stores/branch.store";
import { formatCurrency, formatNumber } from "@/lib/format";
import { PageHeader } from "@/components/layout/page-header";
import { MediaPairUpload } from "@/components/media/media-pair-upload";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { MoneyInput } from "@/components/ui/money-input";
import { LabeledField } from "@/components/ui/labeled-field";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { MenuItemLabels } from "@/components/menu/menu-item-labels";
import { MenuItemMedia } from "@/components/menu/menu-item-media";
import { buildCategoryNameMap, inferMenuItemKind } from "@/lib/menu-item-image";
import { menuItemMatchesSearch } from "@/lib/menu-display";
import { BranchMenuOverrides } from "@/components/menu/branch-menu-overrides";

// ─── Types ────────────────────────────────────────────────────────────────────

interface MenuCategory {
  id: string;
  name: string;
  nameEn?: string;
  nameAr?: string;
  sortOrder: number;
  discountPercent: number;
  icon?: string;
  iconPresetId?: string;
  iconStyle?: string;
  imageUrl?: string;
  isActive: boolean;
}

interface MenuItem {
  id: string;
  categoryId: string;
  name: string;
  nameEn?: string;
  nameAr?: string;
  price: number;
  discountPercent: number;
  imageUrl?: string;
  videoUrl?: string;
  model3dUrl?: string;
  isAvailable: boolean;
}

interface ItemForm {
  categoryId: string;
  name: string;
  nameEn: string;
  price: string;
  discount: string;
  imageUrl: string;
  videoUrl: string;
  model3dUrl: string;
}

interface CatForm {
  name: string;
  icon: string;
  iconPreset: CategoryIconSelection;
  imageUrl: string;
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

function discountedPrice(price: number, percent: number) {
  if (percent <= 0) return price;
  return Math.round(price * (1 - percent / 100));
}

function mediaField(url: string) {
  return url.trim() === "" ? "" : url;
}

const defaultItemForm: ItemForm = {
  categoryId: "",
  name: "",
  nameEn: "",
  price: "",
  discount: "0",
  imageUrl: "",
  videoUrl: "",
  model3dUrl: "",
};

const defaultCatForm: CatForm = {
  name: "",
  icon: "",
  iconPreset: { iconPresetId: null, iconStyle: DEFAULT_CATEGORY_ICON_STYLE },
  imageUrl: "",
};

// ─── Toggle Switch ────────────────────────────────────────────────────────────

function ToggleSwitch({
  checked,
  onChange,
  disabled,
  label,
}: {
  checked: boolean;
  onChange: (v: boolean) => void;
  disabled?: boolean;
  label?: string;
}) {
  return (
    <button
      role="switch"
      aria-checked={checked}
      aria-label={label}
      type="button"
      // Force LTR so the knob's translate-x stays inside the track; in RTL the
      // flex start sits on the right and translate-x-4 would push it out.
      dir="ltr"
      onClick={() => !disabled && onChange(!checked)}
      className={cn(
        "relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-200",
        checked ? "bg-[#0F6E56]" : "bg-slate-300 dark:bg-slate-600",
        disabled && "cursor-not-allowed opacity-50"
      )}
    >
      <span
        className={cn(
          "pointer-events-none block h-4 w-4 rounded-full bg-white shadow-md transition-transform duration-200",
          checked ? "translate-x-4" : "translate-x-0"
        )}
      />
    </button>
  );
}

// ─── Modal wrapper ────────────────────────────────────────────────────────────

function Modal({
  open,
  onClose,
  title,
  children,
  maxWidth = "max-w-lg",
}: {
  open: boolean;
  onClose: () => void;
  title: string;
  children: React.ReactNode;
  maxWidth?: string;
}) {
  if (!open) return null;
  return (
    <div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/50 p-4 pt-12">
      <div
        className={cn(
          "w-full rounded-2xl border border-border bg-background shadow-2xl",
          maxWidth
        )}
      >
        <div className="flex items-center justify-between border-b border-border px-5 py-4">
          <h2 className="text-base font-semibold">{title}</h2>
          <Button type="button" variant="ghost" size="icon" onClick={onClose}>
            <X className="size-4" />
          </Button>
        </div>
        <div className="max-h-[80vh] overflow-y-auto p-5">{children}</div>
      </div>
    </div>
  );
}

// ─── Main Component ───────────────────────────────────────────────────────────

export function MenuAdminScreen() {
  const t = useTranslations("menuAdmin");
  const tCommon = useTranslations("common");
  const apiError = useApiError();
  const showError = (err: unknown) => notify.error(apiError(err));
  const isRtl = useIsRtl();
  const locale = useLocale();
  const numberLocale = locale === "en" ? "en-US" : "fa-IR";
  const cafeId = useAuthStore((s) => s.user?.cafeId);
  const branchId = useBranchStore((s) => s.branchId);
  const queryClient = useQueryClient();

  // ── UI state ───────────────────────────────────────────────────────────────
  const [activeTab, setActiveTab] = useState<"catalog" | "branch">("catalog");
  const [selectedCategoryId, setSelectedCategoryId] = useState<string | "all">("all");
  const [itemSearch, setItemSearch] = useState("");

  // Item modal
  const [itemModalOpen, setItemModalOpen] = useState(false);
  const [editingItem, setEditingItem] = useState<MenuItem | null>(null);
  const [itemForm, setItemForm] = useState<ItemForm>(defaultItemForm);

  // Category modal
  const [catModalOpen, setCatModalOpen] = useState(false);
  const [editingCategory, setEditingCategory] = useState<MenuCategory | null>(null);
  const [catForm, setCatForm] = useState<CatForm>(defaultCatForm);

  // Delete confirmation (shared dialog for items + categories)
  const [confirmDelete, setConfirmDelete] = useState<
    { kind: "item" | "category"; id: string; name: string } | null
  >(null);

  // ── Data queries ───────────────────────────────────────────────────────────
  const { data: categories = [] } = useQuery({
    queryKey: ["menu-categories", cafeId],
    queryFn: () => apiGet<MenuCategory[]>(`/api/cafes/${cafeId}/menu/categories`),
    enabled: !!cafeId,
  });

  const { data: items = [], isLoading } = useQuery({
    queryKey: ["menu-items-all", cafeId],
    queryFn: () => apiGet<MenuItem[]>(`/api/cafes/${cafeId}/menu/items`),
    enabled: !!cafeId,
  });

  const categoryNameById = useMemo(
    () => buildCategoryNameMap(categories),
    [categories]
  );

  // ── Derived data ───────────────────────────────────────────────────────────
  const itemCountByCategory = useMemo(() => {
    const counts: Record<string, number> = {};
    for (const item of items) {
      counts[item.categoryId] = (counts[item.categoryId] ?? 0) + 1;
    }
    return counts;
  }, [items]);

  const filteredItems = useMemo(() => {
    let result = items;
    if (selectedCategoryId !== "all") {
      result = result.filter((i) => i.categoryId === selectedCategoryId);
    }
    const q = itemSearch.trim();
    if (q) {
      result = result.filter((i) => menuItemMatchesSearch(i, q, locale));
    }
    return result;
  }, [items, selectedCategoryId, itemSearch, locale]);

  // ── Mutations ──────────────────────────────────────────────────────────────
  const invalidateMenu = () => {
    queryClient.invalidateQueries({ queryKey: ["menu-items-all", cafeId] });
    queryClient.invalidateQueries({ queryKey: ["menu-categories", cafeId] });
    queryClient.invalidateQueries({ queryKey: ["menu-items", cafeId] });
  };

  const addItemMutation = useMutation({
    mutationFn: () =>
      apiPost(`/api/cafes/${cafeId}/menu/items`, {
        categoryId: itemForm.categoryId,
        name: itemForm.name,
        nameEn: itemForm.nameEn.trim() || null,
        price: parseFloat(itemForm.price),
        discountPercent: parseFloat(itemForm.discount) || 0,
        imageUrl: itemForm.imageUrl || null,
        videoUrl: itemForm.videoUrl || null,
        model3dUrl: itemForm.model3dUrl || null,
      }),
    onSuccess: () => {
      setItemModalOpen(false);
      invalidateMenu();
    },
    onError: showError,
  });

  const updateItemMutation = useMutation({
    mutationFn: (id: string) =>
      apiPatch(`/api/cafes/${cafeId}/menu/items/${id}`, {
        name: itemForm.name,
        nameEn: itemForm.nameEn.trim() || null,
        price: parseFloat(itemForm.price),
        discountPercent: parseFloat(itemForm.discount) || 0,
        imageUrl: mediaField(itemForm.imageUrl),
        videoUrl: mediaField(itemForm.videoUrl),
        model3dUrl: mediaField(itemForm.model3dUrl),
      }),
    onSuccess: () => {
      setItemModalOpen(false);
      invalidateMenu();
    },
    onError: showError,
  });

  const toggleItemMutation = useMutation({
    mutationFn: ({ id, isAvailable }: { id: string; isAvailable: boolean }) =>
      apiPatch(`/api/cafes/${cafeId}/menu/items/${id}/availability`, { isAvailable }),
    onSuccess: invalidateMenu,
    onError: showError,
  });

  const deleteItemMutation = useMutation({
    mutationFn: (id: string) => apiDelete(`/api/cafes/${cafeId}/menu/items/${id}`),
    onSuccess: () => {
      setConfirmDelete(null);
      setItemModalOpen(false);
      notify.success(t("deleteItemSuccess"));
      invalidateMenu();
    },
    onError: showError,
  });

  const deleteCategoryMutation = useMutation({
    mutationFn: (id: string) => apiDelete(`/api/cafes/${cafeId}/menu/categories/${id}`),
    onSuccess: (_data, id) => {
      setConfirmDelete(null);
      setCatModalOpen(false);
      // If the deleted category was selected, fall back to "all items".
      setSelectedCategoryId((prev) => (prev === id ? "all" : prev));
      notify.success(t("deleteCategorySuccess"));
      invalidateMenu();
    },
    onError: showError,
  });

  const addCategoryMutation = useMutation({
    mutationFn: () =>
      apiPost(`/api/cafes/${cafeId}/menu/categories`, {
        name: catForm.name,
        sortOrder: categories.length + 1,
        discountPercent: 0,
        icon: catForm.icon.trim() || null,
        iconPresetId: catForm.iconPreset.iconPresetId,
        iconStyle: catForm.iconPreset.iconPresetId ? catForm.iconPreset.iconStyle : null,
        imageUrl: catForm.imageUrl.trim() || null,
      }),
    onSuccess: () => {
      setCatModalOpen(false);
      invalidateMenu();
    },
    onError: showError,
  });

  const updateCategoryMutation = useMutation({
    mutationFn: (id: string) =>
      apiPatch(`/api/cafes/${cafeId}/menu/categories/${id}`, {
        name: catForm.name,
        icon: mediaField(catForm.icon),
        iconPresetId: catForm.iconPreset.iconPresetId ?? "",
        iconStyle: catForm.iconPreset.iconPresetId ? catForm.iconPreset.iconStyle : "",
        imageUrl: mediaField(catForm.imageUrl),
      }),
    onSuccess: () => {
      setCatModalOpen(false);
      invalidateMenu();
    },
    onError: showError,
  });

  // ── Modal openers ──────────────────────────────────────────────────────────
  const openAddItem = () => {
    setEditingItem(null);
    setItemForm({
      ...defaultItemForm,
      categoryId:
        selectedCategoryId !== "all" ? selectedCategoryId : (categories[0]?.id ?? ""),
    });
    setItemModalOpen(true);
  };

  const openEditItem = (item: MenuItem) => {
    setEditingItem(item);
    setItemForm({
      categoryId: item.categoryId,
      name: item.name,
      nameEn: item.nameEn ?? "",
      price: String(item.price),
      discount: String(item.discountPercent),
      imageUrl: item.imageUrl ?? "",
      videoUrl: item.videoUrl ?? "",
      model3dUrl: item.model3dUrl ?? "",
    });
    setItemModalOpen(true);
  };

  const openAddCategory = () => {
    setEditingCategory(null);
    setCatForm(defaultCatForm);
    setCatModalOpen(true);
  };

  const openEditCategory = (cat: MenuCategory) => {
    setEditingCategory(cat);
    setCatForm({
      name: cat.name,
      icon: cat.icon ?? "",
      iconPreset: {
        iconPresetId: cat.iconPresetId ?? null,
        iconStyle:
          (cat.iconStyle as CategoryIconSelection["iconStyle"]) ??
          DEFAULT_CATEGORY_ICON_STYLE,
      },
      imageUrl: cat.imageUrl ?? "",
    });
    setCatModalOpen(true);
  };

  // ── Form submit handlers ───────────────────────────────────────────────────
  const handleItemSave = () => {
    if (editingItem) {
      updateItemMutation.mutate(editingItem.id);
    } else {
      addItemMutation.mutate();
    }
  };

  const handleCategorySave = () => {
    if (editingCategory) {
      updateCategoryMutation.mutate(editingCategory.id);
    } else {
      addCategoryMutation.mutate();
    }
  };

  const itemMutationBusy =
    addItemMutation.isPending || updateItemMutation.isPending;
  const catMutationBusy =
    addCategoryMutation.isPending || updateCategoryMutation.isPending;

  const itemFormValid =
    itemForm.name.trim() &&
    itemForm.categoryId &&
    itemForm.price &&
    !isNaN(parseFloat(itemForm.price));

  if (!cafeId) return null;

  // ── Tab bar ────────────────────────────────────────────────────────────────
  return (
    <div className="space-y-4" dir={isRtl ? "rtl" : "ltr"}>
      <PageHeader title={t("title")} subtitle={t("subtitle")} />

      {/* Tab switcher */}
      <div className="flex gap-1 rounded-xl border border-border bg-muted/40 p-1 w-fit">
        <button
          type="button"
          onClick={() => setActiveTab("catalog")}
          className={cn(
            "rounded-lg px-4 py-1.5 text-sm font-medium transition-colors cursor-pointer",
            activeTab === "catalog"
              ? "bg-background shadow-sm text-foreground"
              : "text-muted-foreground hover:text-foreground"
          )}
        >
          {t("tabCatalog")}
        </button>
        <button
          type="button"
          onClick={() => setActiveTab("branch")}
          className={cn(
            "rounded-lg px-4 py-1.5 text-sm font-medium transition-colors cursor-pointer",
            activeTab === "branch"
              ? "bg-background shadow-sm text-foreground"
              : "text-muted-foreground hover:text-foreground"
          )}
        >
          {t("tabBranch")}
        </button>
      </div>

      {/* Branch tab */}
      {activeTab === "branch" ? (
        branchId ? (
          <BranchMenuOverrides
            cafeId={cafeId!}
            branchId={branchId}
            numberLocale={numberLocale}
          />
        ) : (
          <p className="rounded-xl border border-border bg-muted/40 p-6 text-center text-sm text-muted-foreground">
            {t("selectBranchForOverrides")}
          </p>
        )
      ) : (
        /* ── Catalog tab ─────────────────────────────────────────────────── */
        <div className="flex min-h-0 flex-col gap-4">
          {categories.length < 5 && items.length < 10 && (
            <DemoDataBanner
              invalidateKeys={[
                ["menu-categories", cafeId],
                ["menu-items-all", cafeId],
                ["menu-items", cafeId],
                ["tables-board", cafeId],
                ["inventory", cafeId],
              ]}
            />
          )}
          <div className="flex min-h-0 gap-4">

          {/* ── Category Sidebar (desktop) ─────────────────────────────── */}
          <aside className="hidden w-52 shrink-0 lg:block">
            <div className="sticky top-4 flex flex-col gap-1 rounded-xl border border-border bg-card p-2 shadow-sm">
              {/* "All items" entry */}
              <button
                type="button"
                onClick={() => setSelectedCategoryId("all")}
                className={cn(
                  "flex w-full cursor-pointer items-center gap-2.5 rounded-lg px-3 py-2.5 text-start text-sm transition-colors",
                  selectedCategoryId === "all"
                    ? "bg-primary/10 font-semibold text-primary"
                    : "text-foreground hover:bg-accent"
                )}
              >
                <span className="size-5 flex items-center justify-center text-base">✦</span>
                <span className="min-w-0 flex-1 truncate">{t("allItems")}</span>
                <span className="shrink-0 rounded-full bg-border/80 px-1.5 py-0.5 text-[10px] text-muted-foreground">
                  {items.length}
                </span>
              </button>

              <div className="my-1 h-px bg-border/60" />

              {/* Category entries */}
              {categories.map((cat) => (
                <div key={cat.id} className="group relative flex items-center">
                  <button
                    type="button"
                    onClick={() => setSelectedCategoryId(cat.id)}
                    className={cn(
                      "flex w-full cursor-pointer items-center gap-2.5 rounded-lg px-3 py-2.5 text-start text-sm transition-colors pe-8",
                      selectedCategoryId === cat.id
                        ? "bg-primary/10 font-semibold text-primary"
                        : "text-foreground hover:bg-accent"
                    )}
                  >
                    <CategoryVisual
                      icon={cat.icon}
                      iconPresetId={cat.iconPresetId}
                      iconStyle={cat.iconStyle}
                      imageUrl={cat.imageUrl}
                      size="xs"
                    />
                    <span className="min-w-0 flex-1 truncate">{cat.name}</span>
                    <span className="shrink-0 rounded-full bg-border/80 px-1.5 py-0.5 text-[10px] text-muted-foreground">
                      {itemCountByCategory[cat.id] ?? 0}
                    </span>
                  </button>
                  {/* Edit category button */}
                  <button
                    type="button"
                    aria-label={t("editCategory")}
                    onClick={() => openEditCategory(cat)}
                    className="absolute end-1 top-1/2 -translate-y-1/2 flex size-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100"
                  >
                    <Pencil className="size-3" />
                  </button>
                </div>
              ))}

              {/* Add category button */}
              <div className="mt-1 border-t border-border/60 pt-1">
                <button
                  type="button"
                  onClick={openAddCategory}
                  className="flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
                >
                  <Plus className="size-4 shrink-0" />
                  {t("addCategory")}
                </button>
              </div>
            </div>
          </aside>

          {/* ── Items panel ────────────────────────────────────────────── */}
          <div className="min-w-0 flex-1">

            {/* Mobile category tabs */}
            <div className="mb-3 flex gap-1.5 overflow-x-auto pb-1 lg:hidden [scrollbar-width:none]">
              <button
                type="button"
                onClick={() => setSelectedCategoryId("all")}
                className={cn(
                  "shrink-0 rounded-full border px-3 py-1 text-xs font-medium transition-colors cursor-pointer",
                  selectedCategoryId === "all"
                    ? "border-primary bg-primary/10 text-primary"
                    : "border-border bg-card text-muted-foreground hover:text-foreground"
                )}
              >
                {t("allItems")} ({items.length})
              </button>
              {categories.map((cat) => (
                <button
                  key={cat.id}
                  type="button"
                  onClick={() => setSelectedCategoryId(cat.id)}
                  className={cn(
                    "shrink-0 flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors cursor-pointer",
                    selectedCategoryId === cat.id
                      ? "border-primary bg-primary/10 text-primary"
                      : "border-border bg-card text-muted-foreground hover:text-foreground"
                  )}
                >
                  <CategoryVisual
                    icon={cat.icon}
                    iconPresetId={cat.iconPresetId}
                    iconStyle={cat.iconStyle}
                    imageUrl={cat.imageUrl}
                    size="xs"
                  />
                  {cat.name}
                  <span className="text-[10px] opacity-60">
                    {itemCountByCategory[cat.id] ?? 0}
                  </span>
                </button>
              ))}
              <button
                type="button"
                onClick={openAddCategory}
                className="shrink-0 flex items-center gap-1 rounded-full border border-dashed border-border px-3 py-1 text-xs text-muted-foreground transition-colors hover:text-foreground cursor-pointer"
              >
                <Plus className="size-3" />
                {t("addCategory")}
              </button>
            </div>

            {/* Search + Add bar */}
            <div className="mb-4 flex items-center gap-2">
              <div className="relative flex-1">
                <Search className="pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" aria-hidden />
                <Input
                  type="search"
                  value={itemSearch}
                  onChange={(e) => setItemSearch(e.target.value)}
                  placeholder={t("searchItemsPlaceholder")}
                  className="h-9 ps-9 pe-9"
                />
                {itemSearch ? (
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="absolute end-1 top-1/2 size-7 -translate-y-1/2"
                    onClick={() => setItemSearch("")}
                  >
                    <X className="size-4" />
                  </Button>
                ) : null}
              </div>
              <Button
                onClick={openAddItem}
                className="shrink-0 bg-[#0F6E56] hover:bg-[#0c5a46]"
                disabled={categories.length === 0}
              >
                <Plus className="me-1.5 size-4" />
                {t("newItem")}
              </Button>
            </div>

            {/* Items grid */}
            {isLoading ? (
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
                {Array.from({ length: 8 }).map((_, i) => (
                  <Skeleton key={i} className="h-52 rounded-xl" />
                ))}
              </div>
            ) : filteredItems.length === 0 ? (
              /* Empty state */
              <div className="flex flex-col items-center gap-3 rounded-2xl border border-dashed border-border py-16 text-center">
                <div className="text-4xl">🍽️</div>
                <p className="text-sm font-medium text-muted-foreground">
                  {itemSearch ? t("noItemsMatchSearch") : t("noItemsInCategory")}
                </p>
                {!itemSearch ? (
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={openAddItem}
                    disabled={categories.length === 0}
                  >
                    <Plus className="me-1.5 size-4" />
                    {t("addItem")}
                  </Button>
                ) : null}
              </div>
            ) : (
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
                {filteredItems.map((item) => {
                  const kind = inferMenuItemKind(
                    item.categoryId,
                    categoryNameById.get(item.categoryId)
                  );
                  const hasDiscount = item.discountPercent > 0;
                  const salePrice = discountedPrice(item.price, item.discountPercent);

                  return (
                    <div
                      key={item.id}
                      className={cn(
                        "group relative flex flex-col overflow-hidden rounded-xl border border-border bg-card shadow-sm transition-all hover:border-primary/40 hover:shadow-md",
                        !item.isAvailable && "opacity-70"
                      )}
                    >
                      {/* Image area */}
                      <div className="relative aspect-[4/3] overflow-hidden bg-muted/50">
                        <MenuItemMedia
                          imageUrl={item.imageUrl}
                          kind={kind}
                          size="md"
                          className="absolute inset-0"
                        />

                        {/* Hover overlay — edit button */}
                        <div className="absolute inset-0 flex items-center justify-center bg-black/0 transition-all group-hover:bg-black/25">
                          <Button
                            size="sm"
                            className="translate-y-2 opacity-0 shadow-lg transition-all group-hover:translate-y-0 group-hover:opacity-100"
                            onClick={() => openEditItem(item)}
                          >
                            <Pencil className="me-1.5 size-3.5" />
                            {t("editItem")}
                          </Button>
                        </div>

                        {/* Discount badge */}
                        {hasDiscount ? (
                          <span className="absolute start-2 top-2 z-10 rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-[10px] font-semibold text-[#BA7517]">
                            {formatNumber(item.discountPercent, numberLocale)}% {t("discountBadge")}
                          </span>
                        ) : null}

                        {/* Media badges */}
                        <div className="absolute bottom-1.5 start-1.5 flex gap-1">
                          {item.videoUrl ? (
                            <span className="flex items-center gap-0.5 rounded-md bg-black/60 px-1.5 py-0.5 text-[10px] text-white">
                              <Video className="size-2.5" />
                            </span>
                          ) : null}
                          {item.model3dUrl ? (
                            <span className="flex items-center gap-0.5 rounded-md bg-[#0F6E56]/90 px-1.5 py-0.5 text-[10px] text-white">
                              <Box className="size-2.5" />
                              3D
                            </span>
                          ) : null}
                        </div>

                        {/* Out of stock overlay */}
                        {!item.isAvailable ? (
                          <div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-[1px]">
                            <span className="rounded-full bg-slate-800/80 px-3 py-1 text-xs font-medium text-white">
                              {t("outOfStock")}
                            </span>
                          </div>
                        ) : null}
                      </div>

                      {/* Body */}
                      <div className="flex items-start gap-2 p-3">
                        <div className="min-w-0 flex-1">
                          <MenuItemLabels
                            item={item}
                            lines={1}
                            primaryClassName="text-sm font-medium"
                            secondaryClassName="text-[10px]"
                          />
                          <div className="mt-1 flex items-baseline gap-1.5">
                            {hasDiscount ? (
                              <>
                                <span className="text-[11px] text-muted-foreground line-through">
                                  {formatCurrency(item.price, numberLocale)}
                                </span>
                                <span className="text-sm font-semibold text-[#0F6E56]">
                                  {formatCurrency(salePrice, numberLocale)}
                                </span>
                              </>
                            ) : (
                              <span className="text-sm font-semibold text-[#0F6E56]">
                                {formatCurrency(item.price, numberLocale)}
                              </span>
                            )}
                          </div>
                        </div>

                        {/* Availability toggle */}
                        <ToggleSwitch
                          checked={item.isAvailable}
                          onChange={(v) =>
                            toggleItemMutation.mutate({ id: item.id, isAvailable: v })
                          }
                          disabled={toggleItemMutation.isPending}
                          label={
                            item.isAvailable ? t("available") : t("unavailable")
                          }
                        />
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
          </div>
        </div>
      )}

      {/* ── Item Add / Edit Modal ─────────────────────────────────────────── */}
      <Modal
        open={itemModalOpen}
        onClose={() => setItemModalOpen(false)}
        title={editingItem ? t("editItem") : t("newItem")}
        maxWidth="max-w-lg"
      >
        <div className="space-y-4">
          {/* Category selector */}
          <LabeledField label={t("category")} htmlFor="modal-item-category">
            <select
              id="modal-item-category"
              className="w-full rounded-lg border border-input bg-background px-3 py-2 text-sm"
              value={itemForm.categoryId}
              onChange={(e) =>
                setItemForm((f) => ({ ...f, categoryId: e.target.value }))
              }
            >
              <option value="">—</option>
              {categories.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
          </LabeledField>

          <div className="grid gap-3 sm:grid-cols-2">
            <LabeledField label={t("name")} htmlFor="modal-item-name">
              <Input
                id="modal-item-name"
                value={itemForm.name}
                onChange={(e) => setItemForm((f) => ({ ...f, name: e.target.value }))}
                autoFocus
              />
            </LabeledField>
            <LabeledField label={t("nameEnOptional")} htmlFor="modal-item-name-en">
              <Input
                id="modal-item-name-en"
                value={itemForm.nameEn}
                onChange={(e) =>
                  setItemForm((f) => ({ ...f, nameEn: e.target.value }))
                }
                dir="ltr"
                className="text-start"
                placeholder="e.g. Espresso"
              />
            </LabeledField>
          </div>

          <div className="grid gap-3 sm:grid-cols-2">
            <LabeledField label={t("price")} htmlFor="modal-item-price">
              <MoneyInput
                id="modal-item-price"
                value={itemForm.price}
                onValueChange={(raw) => setItemForm((f) => ({ ...f, price: raw }))}
              />
            </LabeledField>
            <LabeledField label={t("discountPercent")} htmlFor="modal-item-discount">
              <Input
                id="modal-item-discount"
                value={itemForm.discount}
                onChange={(e) =>
                  setItemForm((f) => ({ ...f, discount: e.target.value }))
                }
                inputMode="numeric"
                dir="ltr"
                className="text-end"
              />
            </LabeledField>
          </div>

          {/* Media */}
          <LabeledField label={t("media")}>
            <MediaPairUpload
              cafeId={cafeId!}
              kind="menu"
              imageUrl={itemForm.imageUrl}
              videoUrl={itemForm.videoUrl}
              onImageChange={(url) =>
                setItemForm((f) => ({ ...f, imageUrl: url ?? "" }))
              }
              onVideoChange={(url) =>
                setItemForm((f) => ({ ...f, videoUrl: url ?? "" }))
              }
            />
          </LabeledField>

          {/* 3D model */}
          <LabeledField label={t("model3d")}>
            <Menu3dUpload
              cafeId={cafeId!}
              model3dUrl={itemForm.model3dUrl || null}
              onChange={(url) =>
                setItemForm((f) => ({ ...f, model3dUrl: url ?? "" }))
              }
            />
            {editingItem ? (
              <MenuAi3dGenerate
                cafeId={cafeId!}
                itemId={editingItem.id}
                imageUrl={itemForm.imageUrl || editingItem.imageUrl}
                onGenerated={(url) =>
                  setItemForm((f) => ({ ...f, model3dUrl: url }))
                }
              />
            ) : null}
          </LabeledField>

          {/* Actions */}
          <div className="flex items-center justify-between gap-2 border-t border-border pt-4">
            {editingItem ? (
              <Button
                type="button"
                variant="ghost"
                className="text-red-600 hover:bg-red-50 hover:text-red-700"
                onClick={() =>
                  setConfirmDelete({
                    kind: "item",
                    id: editingItem.id,
                    name: editingItem.name,
                  })
                }
              >
                <Trash2 className="me-1.5 size-4" />
                {tCommon("delete")}
              </Button>
            ) : (
              <span />
            )}
            <div className="flex gap-2">
              <Button variant="ghost" onClick={() => setItemModalOpen(false)}>
                {tCommon("cancel")}
              </Button>
              <Button
                className="bg-[#0F6E56] hover:bg-[#0c5a46]"
                disabled={!itemFormValid || itemMutationBusy}
                onClick={handleItemSave}
              >
                {itemMutationBusy ? t("saving") : tCommon("save")}
              </Button>
            </div>
          </div>
        </div>
      </Modal>

      {/* ── Category Add / Edit Modal ─────────────────────────────────────── */}
      <Modal
        open={catModalOpen}
        onClose={() => setCatModalOpen(false)}
        title={editingCategory ? t("editCategoryTitle") : t("newCategory")}
        maxWidth="max-w-md"
      >
        <div className="space-y-4">
          <LabeledField label={t("name")} htmlFor="modal-cat-name">
            <Input
              id="modal-cat-name"
              value={catForm.name}
              onChange={(e) => setCatForm((f) => ({ ...f, name: e.target.value }))}
              autoFocus
            />
          </LabeledField>

          <CategoryMediaFields
            cafeId={cafeId!}
            icon={catForm.icon}
            iconPresetId={catForm.iconPreset.iconPresetId}
            iconStyle={catForm.iconPreset.iconStyle}
            imageUrl={catForm.imageUrl}
            onIconChange={(icon) => setCatForm((f) => ({ ...f, icon }))}
            onPresetChange={(iconPreset) => setCatForm((f) => ({ ...f, iconPreset }))}
            onImageChange={(url) =>
              setCatForm((f) => ({ ...f, imageUrl: url ?? "" }))
            }
          />

          <div className="flex items-center justify-between gap-2 border-t border-border pt-4">
            {editingCategory ? (
              <Button
                type="button"
                variant="ghost"
                className="text-red-600 hover:bg-red-50 hover:text-red-700"
                onClick={() =>
                  setConfirmDelete({
                    kind: "category",
                    id: editingCategory.id,
                    name: editingCategory.name,
                  })
                }
              >
                <Trash2 className="me-1.5 size-4" />
                {tCommon("delete")}
              </Button>
            ) : (
              <span />
            )}
            <div className="flex gap-2">
              <Button variant="ghost" onClick={() => setCatModalOpen(false)}>
                {tCommon("cancel")}
              </Button>
              <Button
                className="bg-[#0F6E56] hover:bg-[#0c5a46]"
                disabled={!catForm.name.trim() || catMutationBusy}
                onClick={handleCategorySave}
              >
                {catMutationBusy ? t("saving") : tCommon("save")}
              </Button>
            </div>
          </div>
        </div>
      </Modal>

      {/* ── Delete confirmation (items + categories) ──────────────────────── */}
      <AlertDialog
        open={!!confirmDelete}
        onOpenChange={(open) => {
          if (!open) setConfirmDelete(null);
        }}
      >
        <AlertDialogContent dir={isRtl ? "rtl" : "ltr"}>
          <AlertDialogHeader>
            <AlertDialogTitle>
              {confirmDelete?.kind === "category"
                ? t("deleteCategoryConfirmTitle")
                : t("deleteItemConfirmTitle")}
            </AlertDialogTitle>
            <AlertDialogDescription>
              {confirmDelete?.kind === "category"
                ? t("deleteCategoryConfirmDesc", { name: confirmDelete?.name ?? "" })
                : t("deleteItemConfirmDesc", { name: confirmDelete?.name ?? "" })}
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>{tCommon("cancel")}</AlertDialogCancel>
            <AlertDialogAction
              className="bg-red-600 text-white hover:bg-red-700"
              disabled={deleteItemMutation.isPending || deleteCategoryMutation.isPending}
              onClick={(e) => {
                e.preventDefault(); // keep dialog open until the mutation resolves
                if (!confirmDelete) return;
                if (confirmDelete.kind === "category") {
                  deleteCategoryMutation.mutate(confirmDelete.id);
                } else {
                  deleteItemMutation.mutate(confirmDelete.id);
                }
              }}
            >
              {deleteItemMutation.isPending || deleteCategoryMutation.isPending
                ? t("saving")
                : tCommon("delete")}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
