/**
 * FavoritesPage — My Favorite Vendors page (Task 15).
 *
 * - Auth-gated (enforced at the Astro route level).
 * - Fetches /api/favorites via React Query.
 * - Shows empty state when no favorites saved.
 * - Wraps content in WishlistProvider with initialVendorIds.
 */

'use client';

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useT } from '@/lib/i18n/react';
import { Container } from '@/components/ui/layout/Container';
import { HydratedIsland } from '@/components/HydratedIsland';
import { AppShell } from '@/components/ui/layout/AppShell';
import { BottomNav, useCustomerNavItems } from '@/components/ui/layout/BottomNav';
import { SiteNav } from '@/components/ui/layout/SiteNav';
import { FavoritesSkeleton, SkeletonGuard } from '@/components/ui/feedback/Skeleton';
import { EmptyState } from '@/components/ui/feedback/EmptyState';
import { InlineNotice } from '@/components/ui/feedback/InlineNotice';
import { NoFav } from '@/components/ui/feedback/EmptyState/illustrations';
import { Button } from '@/components/ui/primitives/Button';
import { Switch } from '@/components/ui/primitives/Switch/Switch';
import { Icon } from '@/components/ui/icons/Icon';
import { Label } from '@/components/ui/primitives/Label';
import { WishlistProvider } from '@/features/wishlist/WishlistContext';
import { getCsrfToken } from '@/lib/csrf';
import type { FavoriteVendorRow } from '@/server/db/queries/favorite-vendors';
import type { Locale } from '@/lib/i18n';

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

export interface FavoritesPageProps {
  locale: Locale;
  isGuest?: boolean;
  isAdmin?: boolean;
  isVendor?: boolean;
  userName?: string;
  favoritedVendorIds?: string[];
  initialFavorites?: FavoriteVendorRow[];
}

// ─── Module-level SSR timestamp (captured once at module load, not per render) ─
const MODULE_LOAD_TIME = Date.now();

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

interface FavoritesApiResponse {
  ok: boolean;
  items: FavoriteVendorRow[];
}

function FavoritesPageInner({
  isGuest = false,
  isAdmin = false,
  isVendor = false,
  userName,
  favoritedVendorIds = [],
  initialFavorites,
}: Omit<FavoritesPageProps, 'locale'>) {
  const t = useT('favorites');

  const qc = useQueryClient();

  const { data, isLoading, isError } = useQuery<FavoritesApiResponse>({
    queryKey: ['favorites'],
    queryFn: async () => {
      const res = await fetch('/api/favorites');
      if (!res.ok) throw new Error('Failed to fetch favorites');
      return res.json() as Promise<FavoritesApiResponse>;
    },
    initialData: initialFavorites ? { ok: true, items: initialFavorites } : undefined,
    initialDataUpdatedAt: initialFavorites ? MODULE_LOAD_TIME : 0,
    staleTime: 60_000,
  });

  const items = data?.items ?? [];

  const toggleMutation = useMutation({
    mutationFn: async (vendorId: string) => {
      const cookies = document.cookie.split('; ');
      const csrf = cookies.find((c) => c.startsWith('csrf_token='))?.split('=')[1] ?? '';
      const res = await fetch('/api/favorites/toggle', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrf },
        body: JSON.stringify({ vendorId }),
      });
      if (!res.ok) throw new Error('toggle failed');
      return res.json() as Promise<{ ok: boolean; saved: boolean }>;
    },
    onMutate: async (vendorId) => {
      await qc.cancelQueries({ queryKey: ['favorites'] });
      const prev = qc.getQueryData<FavoritesApiResponse>(['favorites']);
      qc.setQueryData<FavoritesApiResponse>(['favorites'], (old) =>
        old ? { ...old, items: old.items.filter((i) => i.vendorId !== vendorId) } : old,
      );
      return { prev };
    },
    onError: (_err, _vendorId, ctx) => {
      if (ctx?.prev) qc.setQueryData<FavoritesApiResponse>(['favorites'], ctx.prev);
    },
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['favorites'] });
    },
  });

  const notifyMutation = useMutation({
    mutationFn: async ({ vendorId, notify }: { vendorId: string; notify: boolean }) => {
      const csrf = getCsrfToken();
      const res = await fetch('/api/favorites/notify', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrf },
        body: JSON.stringify({ vendorId, notify }),
      });
      if (!res.ok) throw new Error('notify update failed');
    },
    onMutate: async ({ vendorId, notify }) => {
      await qc.cancelQueries({ queryKey: ['favorites'] });
      const prev = qc.getQueryData<FavoritesApiResponse>(['favorites']);
      qc.setQueryData<FavoritesApiResponse>(['favorites'], (old) =>
        old
          ? {
              ...old,
              items: old.items.map((i) => (i.vendorId === vendorId ? { ...i, notify } : i)),
            }
          : old,
      );
      return { prev };
    },
    onError: (_err, _vars, ctx) => {
      if (ctx?.prev) qc.setQueryData<FavoritesApiResponse>(['favorites'], ctx.prev);
    },
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['favorites'] });
    },
  });

  const notifyAllMutation = useMutation({
    mutationFn: async (notify: boolean) => {
      const csrf = getCsrfToken();
      const res = await fetch('/api/favorites/notify-all', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrf },
        body: JSON.stringify({ notify }),
      });
      if (!res.ok) throw new Error('notify-all update failed');
    },
    onMutate: async (notify) => {
      await qc.cancelQueries({ queryKey: ['favorites'] });
      const prev = qc.getQueryData<FavoritesApiResponse>(['favorites']);
      qc.setQueryData<FavoritesApiResponse>(['favorites'], (old) =>
        old ? { ...old, items: old.items.map((i) => ({ ...i, notify })) } : old,
      );
      return { prev };
    },
    onError: (_err, _notify, ctx) => {
      if (ctx?.prev) qc.setQueryData<FavoritesApiResponse>(['favorites'], ctx.prev);
    },
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['favorites'] });
    },
  });

  const navItems = useCustomerNavItems('/favorites');

  return (
    <WishlistProvider initialVendorIds={favoritedVendorIds} isAuthenticated>
      <AppShell
        mode="customer"
        topBar={
          <SiteNav
            variant="mobile"
            title={t('page_title')}
            currentPath="/favorites"
            isGuest={isGuest}
            isAdmin={isAdmin}
            isVendor={isVendor}
          />
        }
        desktopTopBar={
          <SiteNav
            variant="desktop"
            currentPath="/favorites"
            isGuest={isGuest}
            isAdmin={isAdmin}
            isVendor={isVendor}
            userName={userName}
          />
        }
        bottomNav={<BottomNav mode="customer" items={navItems} />}
      >
        <Container maxWidth="4xl" px="6">
          <main id="main" 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('page_title')}
            </h1>

            {isError && (
              <div role="alert" className="mb-4">
                <InlineNotice tone="danger" description={t('empty_description')} />
              </div>
            )}

            {isLoading && !data ? (
              <div aria-busy="true" role="status">
                <span className="sr-only">{t('loading')}</span>
                <SkeletonGuard>
                  <FavoritesSkeleton count={6} />
                </SkeletonGuard>
              </div>
            ) : items.length === 0 ? (
              <EmptyState
                illustration={<NoFav />}
                title={t('empty_title')}
                description={t('empty_description')}
                action={
                  <Button asChild variant="primary" size="md">
                    <a href="/stores">{t('browse_vendors_cta')}</a>
                  </Button>
                }
              />
            ) : (
              <>
                {/* Notify-all toggle */}
                <div className="mb-4 flex items-center justify-between gap-3">
                  <Label htmlFor="favorites-notify-all" className="text-text-secondary text-sm">
                    {t('notify_all_label')}
                  </Label>
                  <Switch
                    id="favorites-notify-all"
                    checked={items.some((i) => i.notify)}
                    onCheckedChange={(v) => notifyAllMutation.mutate(v)}
                    disabled={notifyAllMutation.isPending}
                    aria-label={t('notify_all_label')}
                  />
                </div>
                <ul data-skeleton-ready className="divide-border-subtle divide-y">
                  {items.map((item) => (
                    <li key={item.id} className="py-4">
                      <div className="flex items-center justify-between gap-4">
                        <a
                          href={`/business/${item.vendorId}`}
                          className="text-text-primary hover:text-brand-primary-600 min-w-0 flex-1 font-medium transition-colors"
                        >
                          {item.vendor.displayName}
                        </a>
                        <Switch
                          id={`fav-notify-${item.vendorId}`}
                          checked={item.notify}
                          onCheckedChange={(v) =>
                            notifyMutation.mutate({ vendorId: item.vendorId, notify: v })
                          }
                          disabled={notifyMutation.isPending}
                          aria-label={t('notify_label')}
                        />
                        <Button
                          variant="ghost"
                          size="sm"
                          aria-label={t('remove_from_favorites')}
                          onClick={() => toggleMutation.mutate(item.vendorId)}
                          disabled={toggleMutation.isPending}
                        >
                          <Icon name="Heart" size="sm" aria-hidden />
                        </Button>
                      </div>
                    </li>
                  ))}
                </ul>
              </>
            )}
          </main>
        </Container>
      </AppShell>
    </WishlistProvider>
  );
}

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

export function FavoritesPage({
  locale,
  isGuest = false,
  isAdmin = false,
  isVendor = false,
  userName,
  favoritedVendorIds = [],
  initialFavorites,
}: FavoritesPageProps) {
  return (
    <HydratedIsland locale={locale}>
      <FavoritesPageInner
        isGuest={isGuest}
        isAdmin={isAdmin}
        isVendor={isVendor}
        userName={userName}
        favoritedVendorIds={favoritedVendorIds}
        initialFavorites={initialFavorites}
      />
    </HydratedIsland>
  );
}
