"use client";

import { Search, ShoppingBag, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { QR_ALL_CATEGORY_ID } from "@/lib/qr-menu-constants";
import { MenuItemLabels } from "@/components/menu/menu-item-labels";
import { CategoryVisual } from "@/components/menu/category-visual";
import { formatCurrency } from "@/lib/format";
import { resolveMediaUrl } from "@/lib/api/client";
import { cn } from "@/lib/utils";
import type { QrCartLine, QrPublicMenuCategory, QrPublicMenuItem } from "@/lib/api/qr-public";
import type { CafeThemePalette } from "@/lib/cafe-theme";
import { hasMenu3dView } from "@/lib/menu-3d";
import { Box } from "lucide-react";

export type QrMenuBodyProps = {
  menuStyle: string;
  colors: CafeThemePalette;
  categories: QrPublicMenuCategory[];
  activeCategory: string;
  onCategoryChange: (id: string) => void;
  activeItems: QrPublicMenuItem[];
  showAllGrouped?: boolean;
  searchQuery: string;
  onSearchChange: (value: string) => void;
  isSearching?: boolean;
  categoryNameById?: Map<string, string>;
  cart: QrCartLine[];
  onAdd: (item: QrPublicMenuItem) => void;
  onRemove: (itemId: string) => void;
  onView3d?: (item: QrPublicMenuItem) => void;
  totalItems: number;
  totalPrice: number;
  onOpenCart: () => void;
  labels: {
    emptyCategory: string;
    addToCart: string;
    checkout: string;
    searchPlaceholder: string;
    allCategories: string;
    clearSearch: string;
    view3d: string;
  };
};

export function QrGuestMenuBody({
  showCartBar = true,
  ...props
}: QrMenuBodyProps & { showCartBar?: boolean }) {
  const { colors } = props;
  const primary = colors.primary;
  const surface = colors.surface;

  const style = props.menuStyle || "cards";

  const listProps = {
    ...props,
    primary,
    surface,
    colors,
    showCategoryLabel: props.isSearching ?? false,
    categoryNameById: props.categoryNameById,
  };

  return (
    <div className="min-h-full">
      <MenuSearchBar {...props} primary={primary} surface={surface} />
      <CategoryTabs {...props} primary={primary} surface={surface} colors={colors} />
      {props.showAllGrouped ? (
        <GroupedAllSections {...listProps} />
      ) : style === "grid" ? (
        <GridItems {...listProps} />
      ) : style === "list" ? (
        <ListItems {...listProps} compact={false} />
      ) : style === "compact" ? (
        <ListItems {...listProps} compact />
      ) : style === "magazine" ? (
        <MagazineItems {...listProps} />
      ) : style === "classic" ? (
        <ClassicLayout {...props} surface={surface} />
      ) : (
        <CardItems {...listProps} />
      )}
      {showCartBar ? <CartBar {...props} floating={false} /> : null}
    </div>
  );
}

function MenuSearchBar({
  searchQuery,
  onSearchChange,
  primary,
  surface,
  labels,
}: Pick<QrMenuBodyProps, "searchQuery" | "onSearchChange" | "labels"> & {
  surface: string;
  primary: string;
}) {
  return (
    <div
      className="sticky top-0 z-20 px-3 pb-2 pt-2.5"
      style={{ backgroundColor: surface }}
    >
      <div className="relative">
        <Search
          className="pointer-events-none absolute top-1/2 size-4 -translate-y-1/2 qr-icon start-3"
          aria-hidden
        />
        <Input
          type="search"
          value={searchQuery}
          onChange={(e) => onSearchChange(e.target.value)}
          placeholder={labels.searchPlaceholder}
          className="h-10 rounded-xl qr-border qr-surface ps-9 pe-9 text-sm qr-text"
          style={{ borderColor: `${primary}33` }}
        />
        {searchQuery ? (
          <button
            type="button"
            className="absolute top-1/2 flex size-8 -translate-y-1/2 items-center justify-center rounded-full qr-muted qr-fill-muted end-1"
            onClick={() => onSearchChange("")}
            aria-label={labels.clearSearch}
          >
            <X className="size-4 qr-icon" />
          </button>
        ) : null}
      </div>
    </div>
  );
}

function CategoryTabs({
  categories,
  activeCategory,
  onCategoryChange,
  primary,
  surface,
  colors,
  labels,
}: Pick<QrMenuBodyProps, "categories" | "activeCategory" | "onCategoryChange" | "labels" | "colors"> & {
  surface: string;
  primary: string;
}) {
  return (
    <div
      className="sticky top-[3.25rem] z-10 flex gap-2 overflow-x-auto border-b qr-border px-3 py-2.5 shadow-sm"
      style={{ backgroundColor: surface }}
    >
      <button
        type="button"
        onClick={() => onCategoryChange(QR_ALL_CATEGORY_ID)}
        className={cn(
          "flex shrink-0 items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-medium transition active:scale-[0.98]",
          activeCategory === QR_ALL_CATEGORY_ID ? "text-white" : "qr-border qr-text"
        )}
        style={
          activeCategory === QR_ALL_CATEGORY_ID
            ? { backgroundColor: primary, borderColor: primary }
            : { backgroundColor: "transparent", color: colors.text }
        }
      >
        {labels.allCategories}
      </button>
      {categories.map((cat) => (
        <button
          key={cat.id}
          type="button"
          onClick={() => onCategoryChange(cat.id)}
          className={cn(
            "flex shrink-0 items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-medium transition active:scale-[0.98]",
            activeCategory === cat.id ? "text-white" : "qr-border qr-text"
          )}
          style={
            activeCategory === cat.id
              ? { backgroundColor: primary, borderColor: primary }
              : { backgroundColor: "transparent", color: colors.text }
          }
        >
          <CategoryVisual
            icon={cat.icon}
            iconPresetId={cat.iconPresetId}
            iconStyle={cat.iconStyle}
            imageUrl={cat.imageUrl}
            size="xs"
            brandColors={colors}
          />
          {cat.name}
        </button>
      ))}
    </div>
  );
}

type ItemListExtras = {
  surface: string;
  primary: string;
  colors: CafeThemePalette;
  showCategoryLabel?: boolean;
  categoryNameById?: Map<string, string>;
};

function GroupedAllSections(
  props: Pick<
    QrMenuBodyProps,
    "categories" | "cart" | "onAdd" | "onRemove" | "onView3d" | "labels"
  > &
    ItemListExtras
) {
  const { categories, labels, surface, primary, colors, onView3d } = props;
  const hasAny = categories.some((c) => (c.items?.length ?? 0) > 0);
  if (!hasAny) return <EmptyCategory text={labels.emptyCategory} />;

  return (
    <div className="space-y-4 p-3 pb-4">
      {categories.map((cat) => {
        const items = cat.items ?? [];
        if (items.length === 0) return null;
        return (
          <section key={cat.id}>
            <p className="mb-2 px-1 text-[11px] font-medium uppercase tracking-[0.06em] qr-muted">
              {cat.name}
            </p>
            <div className="space-y-2">
              {items.map((item) => (
                <ItemRowCard
                  key={item.id}
                  item={item}
                  cart={props.cart}
                  primary={primary}
                  surface={surface}
                  colors={colors}
                  onAdd={props.onAdd}
                  onRemove={props.onRemove}
                  onView3d={props.onView3d}
                  addLabel={labels.addToCart}
                  view3dLabel={labels.view3d}
                />
              ))}
            </div>
          </section>
        );
      })}
    </div>
  );
}

function CardItems({
  activeItems,
  cart,
  onAdd,
  onRemove,
  onView3d,
  primary,
  labels,
  surface,
  colors,
  showCategoryLabel,
  categoryNameById,
}: Pick<
  QrMenuBodyProps,
  "activeItems" | "cart" | "onAdd" | "onRemove" | "onView3d" | "labels"
> &
  ItemListExtras) {
  return (
    <div className="space-y-2 p-3 pb-4">
      {activeItems.length === 0 ? (
        <EmptyCategory text={labels.emptyCategory} />
      ) : (
        activeItems.map((item) => (
          <ItemRowCard
            key={item.id}
            item={item}
            cart={cart}
            primary={primary}
            surface={surface}
            colors={colors}
            onAdd={onAdd}
            onRemove={onRemove}
            onView3d={onView3d}
            addLabel={labels.addToCart}
            view3dLabel={labels.view3d}
            categoryLabel={
              showCategoryLabel
                ? categoryNameById?.get(item.categoryId)
                : undefined
            }
          />
        ))
      )}
    </div>
  );
}

function GridItems({
  activeItems,
  cart,
  onAdd,
  onRemove,
  onView3d,
  primary,
  labels,
  surface,
  colors,
  showCategoryLabel,
  categoryNameById,
}: Pick<
  QrMenuBodyProps,
  "activeItems" | "cart" | "onAdd" | "onRemove" | "onView3d" | "labels"
> &
  ItemListExtras) {
  if (activeItems.length === 0) return <EmptyCategory text={labels.emptyCategory} />;
  return (
    <div className="grid grid-cols-2 gap-2.5 p-3 pb-4">
      {activeItems.map((item) => (
        <GridCard
          key={item.id}
          item={item}
          cart={cart}
          primary={primary}
          surface={surface}
          colors={colors}
          onAdd={onAdd}
          onRemove={onRemove}
          onView3d={onView3d}
          addLabel={labels.addToCart}
          view3dLabel={labels.view3d}
          categoryLabel={
            showCategoryLabel ? categoryNameById?.get(item.categoryId) : undefined
          }
        />
      ))}
    </div>
  );
}

function ListItems({
  activeItems,
  cart,
  onAdd,
  onRemove,
  onView3d,
  primary,
  labels,
  surface,
  colors,
  compact,
  showCategoryLabel,
  categoryNameById,
}: Pick<
  QrMenuBodyProps,
  "activeItems" | "cart" | "onAdd" | "onRemove" | "onView3d" | "labels"
> &
  ItemListExtras & { compact: boolean }) {
  return (
    <div className="space-y-2 p-3 pb-4">
      {activeItems.length === 0 ? (
        <EmptyCategory text={labels.emptyCategory} />
      ) : (
        activeItems.map((item) => (
          <div
            key={item.id}
            className={cn(
              "flex items-center gap-2 rounded-lg border border-border/60 px-2 shadow-sm",
              compact ? "py-1.5" : "py-2.5"
            )}
            style={{ backgroundColor: surface }}
          >
            <div className="relative shrink-0">
              {resolveMediaUrl(item.imageUrl) ? (
                <img
                  src={resolveMediaUrl(item.imageUrl)}
                  alt=""
                  className={cn(
                    "rounded-md object-cover",
                    compact ? "size-10" : "size-12"
                  )}
                />
              ) : (
                <div
                  className={cn("rounded-md qr-fill-muted", compact ? "size-10" : "size-12")}
                />
              )}
              {hasMenu3dView(item) && onView3d ? (
                <View3dChip
                  label={labels.view3d}
                  onClick={() => onView3d(item)}
                  className="absolute -bottom-1 end-0 scale-90"
                />
              ) : null}
            </div>
            <div className="min-w-0 flex-1">
              {showCategoryLabel && categoryNameById?.get(item.categoryId) ? (
                <p className="mb-0.5 text-[10px] qr-muted">
                  {categoryNameById.get(item.categoryId)}
                </p>
              ) : null}
              <MenuItemLabels item={item} lines={1} primaryClassName="text-sm font-medium" />
              <p className="text-xs font-semibold" style={{ color: primary }}>
                {formatCurrency(effectivePrice(item), "fa-IR")}
              </p>
            </div>
            <QtyControls
              item={item}
              cart={cart}
              primary={primary}
              onAdd={onAdd}
              onRemove={onRemove}
              addLabel={labels.addToCart}
              small
            />
          </div>
        ))
      )}
    </div>
  );
}

function MagazineItems({
  activeItems,
  cart,
  onAdd,
  onRemove,
  onView3d,
  primary,
  labels,
  surface,
  colors,
  showCategoryLabel,
  categoryNameById,
}: Pick<
  QrMenuBodyProps,
  "activeItems" | "cart" | "onAdd" | "onRemove" | "onView3d" | "labels"
> &
  ItemListExtras) {
  return (
    <div className="space-y-3 p-3 pb-4">
      {activeItems.length === 0 ? (
        <EmptyCategory text={labels.emptyCategory} />
      ) : (
        activeItems.map((item) => {
          const img = resolveMediaUrl(item.imageUrl);
          return (
            <article
              key={item.id}
              className="overflow-hidden rounded-xl border border-border/80 shadow-sm"
              style={{ backgroundColor: surface }}
            >
              <div className="relative">
                {img ? (
                  <img src={img} alt="" className="aspect-[16/9] w-full object-cover" />
                ) : (
                  <div className="aspect-[16/9] w-full qr-fill-muted" />
                )}
                {hasMenu3dView(item) && onView3d ? (
                  <View3dChip
                    label={labels.view3d}
                    onClick={() => onView3d(item)}
                    className="absolute bottom-3 start-3"
                  />
                ) : null}
              </div>
              <div className="p-3">
                {showCategoryLabel && categoryNameById?.get(item.categoryId) ? (
                  <p className="mb-1 text-[10px] qr-muted">
                    {categoryNameById.get(item.categoryId)}
                  </p>
                ) : null}
                <MenuItemLabels item={item} lines={2} primaryClassName="text-base font-semibold" />
                <div className="mt-2 flex items-center justify-between">
                  <span className="font-bold" style={{ color: primary }}>
                    {formatCurrency(effectivePrice(item), "fa-IR")}
                  </span>
                  <QtyControls
                    item={item}
                    cart={cart}
                    primary={primary}
                    onAdd={onAdd}
                    onRemove={onRemove}
                    addLabel={labels.addToCart}
                  />
                </div>
              </div>
            </article>
          );
        })
      )}
    </div>
  );
}

function ClassicLayout({
  categories,
  activeCategory,
  onCategoryChange,
  activeItems,
  showAllGrouped,
  cart,
  onAdd,
  onRemove,
  onView3d,
  colors,
  labels,
  surface,
}: QrMenuBodyProps & { surface: string }) {
  const primary = colors.primary;
  return (
    <div className="flex min-h-[50vh]">
      <aside
        className="w-[4.5rem] shrink-0 space-y-2 border-e border-border/60 py-3"
        style={{ backgroundColor: surface }}
      >
        <button
          type="button"
          onClick={() => onCategoryChange(QR_ALL_CATEGORY_ID)}
          className={cn(
            "mx-auto flex w-14 flex-col items-center gap-1 rounded-lg py-2 text-[10px] font-medium transition",
            activeCategory === QR_ALL_CATEGORY_ID ? "text-white" : "qr-text"
          )}
          style={
            activeCategory === QR_ALL_CATEGORY_ID
              ? { backgroundColor: primary }
              : { color: colors.text }
          }
        >
          <span className="text-base">☰</span>
          <span className="line-clamp-2 text-center leading-tight">{labels.allCategories}</span>
        </button>
        {categories.map((cat) => (
          <button
            key={cat.id}
            type="button"
            onClick={() => onCategoryChange(cat.id)}
            className={cn(
              "mx-auto flex w-14 flex-col items-center gap-1 rounded-lg py-2 text-[10px] font-medium transition",
              activeCategory === cat.id ? "text-white" : "qr-text"
            )}
            style={
              activeCategory === cat.id
                ? { backgroundColor: primary }
                : { color: colors.text }
            }
          >
            <CategoryVisual
              icon={cat.icon}
              iconPresetId={cat.iconPresetId}
              iconStyle={cat.iconStyle}
              imageUrl={cat.imageUrl}
              size="sm"
              brandColors={colors}
            />
            <span className="line-clamp-2 text-center leading-tight">{cat.name}</span>
          </button>
        ))}
      </aside>
      <div className="min-w-0 flex-1">
        {showAllGrouped ? (
          <GroupedAllSections
            categories={categories}
            cart={cart}
            onAdd={onAdd}
            onRemove={onRemove}
            onView3d={onView3d}
            primary={primary}
            labels={labels}
            surface={surface}
            colors={colors}
          />
        ) : (
          <CardItems
            activeItems={activeItems}
            cart={cart}
            onAdd={onAdd}
            onRemove={onRemove}
            onView3d={onView3d}
            primary={primary}
            labels={labels}
            surface={surface}
            colors={colors}
          />
        )}
      </div>
    </div>
  );
}

function ItemRowCard({
  item,
  cart,
  primary,
  surface,
  colors,
  onAdd,
  onRemove,
  onView3d,
  addLabel,
  view3dLabel,
  categoryLabel,
}: {
  item: QrPublicMenuItem;
  cart: QrCartLine[];
  primary: string;
  surface: string;
  colors: CafeThemePalette;
  onAdd: (item: QrPublicMenuItem) => void;
  onRemove: (itemId: string) => void;
  onView3d?: (item: QrPublicMenuItem) => void;
  addLabel: string;
  view3dLabel: string;
  categoryLabel?: string;
}) {
  const img = resolveMediaUrl(item.imageUrl);
  return (
    <div
      className="flex gap-3 rounded-xl border border-border/70 p-3 shadow-sm"
      style={{ backgroundColor: surface }}
    >
      <div className="relative shrink-0">
        {img ? (
          <img src={img} alt="" className="size-[4.5rem] rounded-lg object-cover" />
        ) : (
          <div className="size-[4.5rem] rounded-lg qr-fill-muted" />
        )}
        {hasMenu3dView(item) && onView3d ? (
          <View3dChip
            label={view3dLabel}
            onClick={() => onView3d(item)}
            className="absolute bottom-1 end-1"
          />
        ) : null}
      </div>
      <div className="min-w-0 flex-1">
        {categoryLabel ? (
          <p className="mb-0.5 text-[10px] font-medium qr-muted">{categoryLabel}</p>
        ) : null}
        <div className="qr-text">
          <MenuItemLabels item={item} lines={2} primaryClassName="text-sm font-semibold" />
        </div>
        {item.description ? (
          <p className="mt-0.5 line-clamp-2 text-[11px] qr-muted">
            {item.description}
          </p>
        ) : null}
        <div className="mt-2 flex items-center justify-between gap-2">
          <span className="text-sm font-semibold" style={{ color: primary }}>
            {formatCurrency(effectivePrice(item), "fa-IR")}
          </span>
          <QtyControls
            item={item}
            cart={cart}
            primary={primary}
            onAdd={onAdd}
            onRemove={onRemove}
            addLabel={addLabel}
          />
        </div>
      </div>
    </div>
  );
}

function GridCard({
  item,
  cart,
  primary,
  surface,
  colors,
  onAdd,
  onRemove,
  onView3d,
  addLabel,
  view3dLabel,
  categoryLabel,
}: {
  item: QrPublicMenuItem;
  cart: QrCartLine[];
  primary: string;
  surface: string;
  colors: CafeThemePalette;
  onAdd: (item: QrPublicMenuItem) => void;
  onRemove: (itemId: string) => void;
  onView3d?: (item: QrPublicMenuItem) => void;
  addLabel: string;
  view3dLabel: string;
  categoryLabel?: string;
}) {
  const img = resolveMediaUrl(item.imageUrl);
  return (
    <article
      className="flex flex-col overflow-hidden rounded-xl border border-border/80 shadow-sm"
      style={{ backgroundColor: surface }}
    >
      <div className="relative">
        {img ? (
          <img src={img} alt="" className="aspect-square w-full object-cover" />
        ) : (
          <div className="aspect-square w-full qr-fill-muted" />
        )}
        {hasMenu3dView(item) && onView3d ? (
          <View3dChip label={view3dLabel} onClick={() => onView3d(item)} className="absolute bottom-2 start-2" />
        ) : null}
      </div>
      <div className="flex flex-1 flex-col p-2">
        {categoryLabel ? (
          <p className="mb-0.5 text-[10px] qr-muted">{categoryLabel}</p>
        ) : null}
        <div className="qr-text">
          <MenuItemLabels item={item} lines={2} primaryClassName="text-xs font-semibold" />
        </div>
        <p className="mt-1 text-xs font-bold" style={{ color: primary }}>
          {formatCurrency(effectivePrice(item), "fa-IR")}
        </p>
        <div className="mt-auto pt-2">
          <QtyControls
            item={item}
            cart={cart}
            primary={primary}
            onAdd={onAdd}
            onRemove={onRemove}
            addLabel={addLabel}
            small
          />
        </div>
      </div>
    </article>
  );
}

function QtyControls({
  item,
  cart,
  primary,
  onAdd,
  onRemove,
  addLabel,
  small,
}: {
  item: QrPublicMenuItem;
  cart: QrCartLine[];
  primary: string;
  onAdd: (item: QrPublicMenuItem) => void;
  onRemove: (itemId: string) => void;
  addLabel: string;
  small?: boolean;
}) {
  const inCart = cart.find((c) => c.item.id === item.id);
  const size = small ? "size-7 text-base" : "size-8 text-lg";
  if (inCart) {
    return (
      <div className="flex items-center gap-1.5">
        <QtyBtn label="−" className={size} variant="outline" color={primary} onClick={() => onRemove(item.id)} />
        <span className="min-w-5 text-center text-sm font-bold">{inCart.qty}</span>
        <QtyBtn label="+" className={size} variant="filled" color={primary} onClick={() => onAdd(item)} />
      </div>
    );
  }
  return (
    <Button
      size="sm"
      className="h-8 rounded-full px-3 text-xs"
      style={{ backgroundColor: primary }}
      onClick={() => onAdd(item)}
    >
      {addLabel}
    </Button>
  );
}

function QtyBtn({
  label,
  className,
  variant,
  color,
  onClick,
}: {
  label: string;
  className: string;
  variant: "outline" | "filled";
  color: string;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "flex items-center justify-center rounded-full leading-none",
        className,
        variant === "filled" ? "text-white" : ""
      )}
      style={
        variant === "filled"
          ? { backgroundColor: color }
          : { border: `1.5px solid ${color}`, color }
      }
    >
      {label}
    </button>
  );
}

function View3dChip({
  label,
  onClick,
  className,
}: {
  label: string;
  onClick: () => void;
  className?: string;
}) {
  return (
    <button
      type="button"
      onClick={(e) => {
        e.stopPropagation();
        onClick();
      }}
      className={cn(
        "flex items-center gap-1 rounded-md bg-black/70 px-2 py-1 text-[10px] font-medium text-white shadow-sm backdrop-blur-sm transition active:scale-[0.98]",
        className
      )}
    >
      <Box className="h-3 w-3 shrink-0" aria-hidden />
      {label}
    </button>
  );
}

export function QrFloatingCartBar(
  props: Pick<QrMenuBodyProps, "totalItems" | "totalPrice" | "colors" | "onOpenCart" | "labels">
) {
  return <CartBar {...props} floating />;
}

function CartBar({
  totalItems,
  totalPrice,
  colors,
  onOpenCart,
  labels,
  floating = true,
}: Pick<QrMenuBodyProps, "totalItems" | "totalPrice" | "colors" | "onOpenCart" | "labels"> & {
  floating?: boolean;
}) {
  const primary = colors.primary;
  if (totalItems <= 0) return null;
  return (
    <div
      className={cn(
        floating
          ? "shadow-lg"
          : "sticky bottom-0 z-20 border-t border-border/60 qr-surface/95 backdrop-blur"
      )}
    >
      <Button
        className="flex h-12 w-full items-center justify-between gap-3 rounded-2xl px-4 shadow-md"
        style={{ backgroundColor: primary }}
        onClick={onOpenCart}
      >
        <span className="flex size-7 items-center justify-center rounded-full bg-white/25 text-sm font-bold">
          {totalItems.toLocaleString("fa-IR")}
        </span>
        <span className="flex items-center gap-2 font-semibold">
          <ShoppingBag className="size-4 shrink-0 text-white" aria-hidden />
          {labels.checkout}
        </span>
        <span className="text-sm font-bold">{formatCurrency(totalPrice, "fa-IR")}</span>
      </Button>
    </div>
  );
}

function EmptyCategory({ text }: { text: string }) {
  return <p className="p-8 text-center text-sm qr-muted">{text}</p>;
}

function effectivePrice(item: QrPublicMenuItem): number {
  const discount = item.discountPercent > 0 ? item.discountPercent : 0;
  return Math.round(item.price * (1 - discount / 100));
}
