/**
 * CartPage — full cart management page (W2-B).
 *
 * - Renders CartLineItem list for all cart lines.
 * - Shows subtotal + total breakdown.
 * - "Checkout" CTA: navigates to /cart (W2-C will wire actual checkout flow).
 * - Empty state via CartEmptyState.
 * - CartStaleToast when the API response includes a `removed` array.
 * - CartDrawer available via CartNavButton in navbar surfaces (shared store).
 */

'use client';

import { useState, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useT } from '@/lib/i18n/react';
import { Container } from '@/components/ui/layout/Container';
import {
  ToastProvider,
  ToastViewport,
  Toast,
  ToastTitle,
  ToastDescription,
  ToastClose,
  ToastAction,
} from '@/components/ui/overlays/Toast';
import { useToast } from '@/components/ui/overlays/Toast/useToast';
import { mountToastBridge } from '@/lib/query/toast-bridge';
import { AppShell } from '@/components/ui/layout/AppShell';
import { BottomNav, useCustomerNavItems } from '@/components/ui/layout/BottomNav';
import { SiteNav } from '@/components/ui/layout/SiteNav';
import { CartSkeleton, SkeletonGuard } from '@/components/ui/feedback/Skeleton';
import { CartLineItem } from '@/components/ui/domain/cart/CartLineItem';
import { CartEmptyState } from '@/components/ui/domain/cart/CartEmptyState';
import { CartStaleToast } from '@/components/ui/domain/cart/CartStaleToast';
import { CartDrawer } from '@/components/ui/domain/cart/CartDrawer';
import type { CartLineItemData } from '@/components/ui/domain/cart/CartLineItem/CartLineItem';
import type { RemovedItem } from '@/components/ui/domain/cart/CartStaleToast/CartStaleToast';
import { useCart, type CartItem } from './useCart';
import { useCartDrawerStore } from './cartDrawerStore';
import { CartCheckout } from './CartCheckout';
import type { SavedPaymentMethod } from './CartCheckout';
import type { Locale } from '@/lib/i18n';
import { VatBreakdown } from '@/components/ui/domain/VatBreakdown/VatBreakdown';
import { formatAgorotShekels } from '@/lib/money';

// ─── Props ─────────────────────────────────────────────────────────────────

export interface CartPageProps {
  locale: Locale;
  isGuest?: boolean;
  isAdmin?: boolean;
  isVendor?: boolean;
  userName?: string;
  /** Saved payment methods for registered users. */
  paymentMethods?: SavedPaymentMethod[];
  /** VAT rate percentage (e.g. 17 for 17%). Falls back to 17 if omitted. */
  vatRatePercent?: number;
}

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

/** Map useCart CartItem to CartLineItemData — snapshot fields are optional. */
function toLineItemData(item: CartItem): CartLineItemData {
  return {
    // CartLineItemData.dealId is used as a line identifier by CartLineItem callbacks.
    // We pass dealSkuId here since lines are now keyed by SKU (Task 9).
    dealId: item.dealSkuId,
    imageId: item.imageId,
    title: item.title,
    vendorName: item.vendorName,
    unitPrice: item.unitPrice,
    qty: item.qty,
    maxQty: item.maxQty,
    qtyTiers: item.qtyTiers ?? [],
  };
}

// ─── Inner component (needs QueryClient + i18n context) ────────────────────

function CartPageInner({
  isGuest = true,
  isAdmin = false,
  isVendor = false,
  userName,
  paymentMethods = [],
  vatRatePercent,
}: Omit<CartPageProps, 'locale'>) {
  const t = useT('cart');
  const { toasts, toast, dismiss } = useToast();

  // Wire toast-bridge so optimistic mutation helpers can enqueue toasts outside React.
  useEffect(() => {
    mountToastBridge(toast);
  }, [toast]);

  const {
    items,
    subtotal,
    isLoading,
    updateQty,
    remove,
    pendingUndo,
    undoPendingChange,
    dismissPendingUndo,
  } = useCart({
    onError: (code) => {
      toast({
        title:
          code === 'OUT_OF_STOCK'
            ? t('outOfStock')
            : code === 'MAX_REACHED'
              ? t('maxReached')
              : t('checkout_error'),
        description: code === 'NETWORK' ? t('loading') : undefined,
        tone: code === 'NETWORK' ? 'danger' : 'warning',
      });
    },
  });

  // Stale items removed by the server — shown as a toast when present
  // setRemovedItems is called externally in future when useCart exposes removed[]
  const [removedItems, _setRemovedItems] = useState<RemovedItem[]>([]);

  // Detect stale removals from the server (the removed[] field on GET /api/cart)
  // The useCart hook currently doesn't surface the removed array directly.
  // W2-C follow-up: extend useCart to expose it. Read from the query cache directly; useCart does not expose it.
  // If removedItems are set externally (future), they'll appear automatically.
  useEffect(() => {
    if (removedItems.length > 0) {
      toast({
        title: t('removedSoldOut'),
        tone: 'warning',
        duration: 8000,
      });
    }
  }, [removedItems, t, toast]);

  const subtotalILS = formatAgorotShekels(subtotal);
  const totalILS = subtotalILS; // no extra fees at this phase

  // Drawer state from shared store
  const drawerOpen = useCartDrawerStore((s) => s.open);
  const setDrawerOpen = useCartDrawerStore((s) => s.setOpen);

  const navItems = useCustomerNavItems('/cart');

  const lineItems = items.map(toLineItemData);

  // Get cart deal IDs to exclude from upsell (dealId is optional, filter out undefined)
  const cartDealIds = items.map((i) => i.dealId).filter((id): id is string => id !== undefined);

  // Upsell is optional / non-blocking content. We surface isError so the
  // section is hidden on failure rather than silently rendering an empty list
  // that would otherwise misrepresent state.
  const { data: upsellData, isError: upsellIsError } = useQuery({
    queryKey: ['wishlist-upsell', cartDealIds],
    queryFn: async () => {
      const params = new URLSearchParams();
      cartDealIds.forEach((id) => params.append('exclude', id));
      const res = await fetch(`/api/wishlist/upsell?${params}`);
      if (!res.ok)
        return {
          items: [] as Array<{
            dealId: string;
            deal: { id: string; title: string; discountedPrice: string; heSlug?: string | null };
          }>,
        };
      return res.json() as Promise<{
        ok: true;
        items: Array<{
          dealId: string;
          deal: { id: string; title: string; discountedPrice: string; heSlug?: string | null };
        }>;
      }>;
    },
    enabled: !isLoading, // only after cart is loaded
  });
  const upsellItems = upsellIsError ? [] : (upsellData?.items ?? []);

  return (
    <ToastProvider swipeDirection="left">
      <AppShell
        mode="customer"
        topBar={
          <SiteNav
            variant="mobile"
            title={t('title')}
            currentPath="/cart"
            isGuest={isGuest}
            isAdmin={isAdmin}
            isVendor={isVendor}
          />
        }
        desktopTopBar={
          <SiteNav
            variant="desktop"
            currentPath="/cart"
            isGuest={isGuest}
            isAdmin={isAdmin}
            isVendor={isVendor}
            userName={userName}
          />
        }
        bottomNav={<BottomNav mode="customer" items={navItems} />}
      >
        <Container maxWidth="4xl" px="6">
          <div className="mx-auto max-w-2xl py-6">
            <h1 className="text-text-primary mb-6 text-[length:var(--font-size-display)] leading-tight font-[var(--font-weight-extrabold)]">
              {t('title')}
            </h1>

            {isLoading ? (
              <div aria-busy="true" role="status">
                <span className="sr-only">{t('loading')}</span>
                <SkeletonGuard delay={0}>
                  <CartSkeleton />
                </SkeletonGuard>
              </div>
            ) : items.length === 0 ? (
              <CartEmptyState
                onBrowse={() => {
                  window.location.href = '/';
                }}
              />
            ) : (
              <>
                {/* Line items */}
                <ul className="divide-border-subtle divide-y">
                  {lineItems.map((item) => (
                    <li key={item.dealId}>
                      <CartLineItem
                        item={item}
                        onQtyChange={(dealId, qty) => updateQty(dealId, qty)}
                        onRemove={(dealId) => remove(dealId)}
                        loading={isLoading}
                      />
                    </li>
                  ))}
                </ul>

                {/* Stale toast content (inline on page, not a floating toast) */}
                {removedItems.length > 0 && (
                  <div className="bg-surface-raised mt-4 rounded-xl p-4 shadow-md">
                    <CartStaleToast removedItems={removedItems} />
                  </div>
                )}

                {/* Totals */}
                <div className="border-border-subtle mt-6 space-y-2 border-t pt-4">
                  <div className="flex items-center justify-between text-sm">
                    <span className="text-text-secondary">{t('subtotal')}</span>
                    <span className="text-text-primary font-medium">{subtotalILS}</span>
                  </div>
                  <div className="flex items-center justify-between text-base font-semibold">
                    <span className="text-text-primary">{t('total')}</span>
                    <span className="text-brand-primary-700">{totalILS}</span>
                  </div>
                </div>

                {vatRatePercent !== undefined && subtotal > 0 && (
                  <VatBreakdown
                    totalAgorot={subtotal}
                    vatRatePercent={vatRatePercent}
                    className="mt-3"
                  />
                )}

                {/* Wishlist upsell */}
                {upsellItems.length > 0 && (
                  <section className="mt-8">
                    <h2 className="text-text-primary mb-3 text-2xl font-[var(--font-weight-extrabold)]">
                      {t('wishlist_upsell_title')}
                    </h2>
                    <div className="flex gap-3 overflow-x-auto pb-2">
                      {upsellItems.map((item) => (
                        <a
                          key={item.dealId}
                          href={item.deal.heSlug ? `/deals/${item.deal.heSlug}` : '/deals'}
                          className="bg-surface-default w-48 shrink-0 rounded-2xl p-3 text-sm shadow-md transition-shadow hover:shadow-lg"
                        >
                          <p className="text-text-primary truncate font-medium">
                            {item.deal.title}
                          </p>
                          <p className="text-text-muted mt-1">{item.deal.discountedPrice}</p>
                        </a>
                      ))}
                    </div>
                  </section>
                )}

                {/* Checkout — W2-C */}
                <div id="checkout" className="mt-8">
                  <CartCheckout isRegistered={!isGuest} paymentMethods={paymentMethods} />
                </div>
              </>
            )}
          </div>
        </Container>
      </AppShell>

      {/* Cart drawer — single mount for this page */}
      <CartDrawer
        open={drawerOpen}
        onOpenChange={setDrawerOpen}
        items={lineItems}
        subtotal={subtotal}
        onViewCart={() => {
          setDrawerOpen(false);
        }}
        onCheckout={() => {
          setDrawerOpen(false);
          window.location.href = '/cart';
        }}
        onQtyChange={(dealId, qty) => updateQty(dealId, qty)}
        onRemove={(dealId) => remove(dealId)}
        loading={isLoading}
      />

      {/* Floating toasts */}
      <ToastViewport />
      {pendingUndo && (
        <Toast
          key={pendingUndo.id}
          tone="neutral"
          duration={pendingUndo.duration}
          open
          onOpenChange={(open) => {
            if (!open) dismissPendingUndo();
          }}
        >
          <div className="flex w-full items-start justify-between gap-3">
            <div className="min-w-0">
              <ToastTitle>
                {(pendingUndo.nextQty <= 0 ? t('undo_remove_toast') : t('undo_qty_toast'))
                  .replace('{item}', pendingUndo.itemLabel)
                  .replace('{qty}', String(pendingUndo.previousQty))}
              </ToastTitle>
            </div>
            <div className="flex items-center gap-2">
              <ToastAction altText={t('undo_action')} onClick={undoPendingChange}>
                {t('undo_action')}
              </ToastAction>
              <ToastClose />
            </div>
          </div>
        </Toast>
      )}
      {toasts.map((t) => (
        <Toast
          key={t.id}
          tone={t.tone}
          duration={t.duration}
          open
          onOpenChange={() => dismiss(t.id)}
        >
          <div className="flex w-full items-start justify-between gap-2">
            <div>
              <ToastTitle>{t.title}</ToastTitle>
              {t.description && <ToastDescription>{t.description}</ToastDescription>}
            </div>
            <ToastClose />
          </div>
        </Toast>
      ))}
    </ToastProvider>
  );
}

// ─── Exported page component ───────────────────────────────────────────────

/**
 * CartPage - exported island component.
 * Self-wraps with HydratedIsland so that useQuery inside CartPageInner
 * is always called within a QueryClientProvider, even during Astro SSR
 * slot serialization with client:only="react".
 */
import { HydratedIsland } from '@/components/HydratedIsland';

export function CartPage({
  locale,
  isGuest = true,
  isAdmin = false,
  isVendor = false,
  userName,
  paymentMethods = [],
  vatRatePercent,
}: CartPageProps) {
  return (
    <HydratedIsland locale={locale}>
      <CartPageInner
        isGuest={isGuest}
        isAdmin={isAdmin}
        isVendor={isVendor}
        userName={userName}
        paymentMethods={paymentMethods}
        vatRatePercent={vatRatePercent}
      />
    </HydratedIsland>
  );
}
