import { createFileRoute, Link, useNavigate, notFound } from '@tanstack/react-router';
import { useState, useEffect, useMemo, useRef } from 'react';
import { Minus, Plus, Star, ChevronRight, Check, X, ZoomIn, Truck, Shield, RotateCcw, Info, FlaskConical, ExternalLink } from 'lucide-react';
import { AnimatePresence, motion } from 'framer-motion';
import { labTestEntries, matchLabTestForProduct } from '@/data/labTests';
import { labResultText } from '@/data/labTests';
import { getLabtests } from '@/lib/content.functions';
import AddToCartButton from '@/components/AddToCartButton';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import ShippingEstimate from '@/components/ShippingEstimate';
import { Skeleton } from '@/components/ui/skeleton';
import { products as mockProducts } from '@/data/mockProducts';
import { useGqlCart } from '@/hooks/useGqlCart';
import { useCartDrawerStore } from '@/stores/cartDrawerStore';
import ProductAssistant from '@/components/ProductAssistant';
import ProductCard from '@/components/ProductCard';
import Breadcrumbs from '@/components/Breadcrumbs';
import { useBundleItems, bundleItemsQueryOptions } from '@/hooks/useWooCommerce';
import { toast } from 'sonner';
import { useProduct, useProducts, useProductVariations, useProductReviews, transformProduct } from '@/hooks/useWooCommerce';
import { wc, type WcVariation } from '@/lib/woocommerce';
import { sanitizedHtml, stripHtml } from '@/lib/sanitize';
import StarRating from '@/components/StarRating';
import { productSchema, breadcrumbSchema } from '@/lib/schemas';
import { trackEcommerce } from '@/lib/analytics';
import { useT, useLang, headLang, localizePath, SITE_URL, locale } from '@/lib/i18n';

export const Route = createFileRoute('/product/$slug')({
  loader: async ({ params, context }) => {
    let data: { product: Awaited<ReturnType<typeof transformProduct>> | null; bundleItems: { name: string; slug: string; qty: number }[] };
    try {
      const product = await context.queryClient.ensureQueryData({
        queryKey: ['wc-product', params.slug],
        queryFn: async () => {
          const result = await wc.getProduct(params.slug);
          return transformProduct(result.data);
        },
        staleTime: 5 * 60 * 1000,
      });
      // Bundle contents are fetched server-side so they're in the HTML and structured data.
      let bundleItems: { name: string; slug: string; qty: number }[] = [];
      if (product?.bundleItems?.length) {
        try {
          const items = await context.queryClient.ensureQueryData(bundleItemsQueryOptions(product.bundleItems));
          bundleItems = items.map((b) => ({ name: b.name, slug: b.slug, qty: b.qty }));
        } catch { /* contents stay client-side */ }
      }
      data = { product, bundleItems };
    } catch {
      const fallback = mockProducts.find((p) => p.slug === params.slug);
      data = { product: (fallback as never) ?? null, bundleItems: [] };
    }
    // Unknown slug: real 404 instead of an empty 200 page (soft 404 for Google).
    if (!data.product) throw notFound();
    // Lab reports come from the admin panel; without them the list in this
    // codebase is used, so the badge keeps working on a fresh install.
    return { ...data, labtests: await getLabtests() };
  },
  head: (ctx) => {
    const { params, loaderData } = ctx;
    const lang = headLang(ctx);
    const p = loaderData?.product;
    const name = p?.name ?? params.slug;
    const title = lang === 'en' ? `Buy ${name} | Peptidewinkel` : `${name} Kopen | Peptidewinkel`;
    const description = p?.shortDescription
      ? stripHtml(p.shortDescription).slice(0, 155)
      : (lang === 'en'
          ? `Buy ${name} at Peptidewinkel. Discreet shipping and fast delivery.`
          : `${name} kopen bij Peptidewinkel. Discrete verzending en snelle levering.`);
    const url = `${SITE_URL}${localizePath(`/product/${params.slug}`, lang)}`;
    const nlUrl = `${SITE_URL}/product/${params.slug}`;
    const image = p?.image || `${SITE_URL}/og-image.png`;
    return {
      meta: [
        { title },
        { name: 'description', content: description },
        { property: 'og:title', content: title },
        { property: 'og:description', content: description },
        { property: 'og:type', content: 'product' },
        { property: 'og:url', content: url },
        { property: 'og:image', content: image },
        { property: 'og:site_name', content: 'Peptidewinkel' },
        { property: 'og:locale', content: lang === 'en' ? 'en_GB' : 'nl_NL' },
        { name: 'twitter:card', content: 'summary_large_image' },
        { name: 'twitter:title', content: title },
        { name: 'twitter:description', content: description },
        { name: 'twitter:image', content: image },
      ],
      links: [
        { rel: 'canonical', href: url },
        { rel: 'alternate', hrefLang: 'nl-NL', href: nlUrl },
        { rel: 'alternate', hrefLang: 'en-GB', href: `${SITE_URL}${localizePath(`/product/${params.slug}`, 'en')}` },
        { rel: 'alternate', hrefLang: 'x-default', href: nlUrl },
      ],
      scripts: p
        ? [
            { type: 'application/ld+json', children: JSON.stringify(productSchema(p, { lang, bundleItems: loaderData?.bundleItems })) },
            {
              type: 'application/ld+json',
              children: JSON.stringify(
                breadcrumbSchema([
                  { name: 'Home', url: '/' },
                  { name: p.category, url: `/product-category/${p.categorySlug}` },
                  { name: p.name, url: `/product/${p.slug}` },
                ]),
              ),
            },
          ]
        : [],
    };
  },
  component: SingleProduct,
});

function SingleProduct() {
  const t = useT();
  const { slug } = Route.useParams();
  const { labtests } = Route.useLoaderData();
  const { addItem, addPending } = useGqlCart();
  const openCart = useCartDrawerStore((s) => s.open);
  const [quantity, setQuantity] = useState(1);
  const [activeTab, setActiveTab] = useState<'description' | 'info' | 'reviews'>('description');
  const [selectedImage, setSelectedImage] = useState(0);
  const [lightboxOpen, setLightboxOpen] = useState(false);

  const { data: product, isLoading } = useProduct(slug || '');
  const fallbackProduct = mockProducts.find((p) => p.slug === slug);
  const displayProduct = product || fallbackProduct;
  const { data: bundleItems } = useBundleItems(displayProduct?.bundleItems);

  const { data: reviewsResult, isLoading: reviewsLoading } = useProductReviews(
    activeTab === 'reviews' ? product?.id : undefined
  );
  const reviews = reviewsResult?.data || [];

  const hasVariations = displayProduct?.type === 'variable' && (displayProduct.variations?.length ?? 0) > 0;
  const { data: variationsResult } = useProductVariations(hasVariations ? displayProduct?.id : undefined);
  const variations: WcVariation[] = useMemo(() => variationsResult?.data || [], [variationsResult?.data]);

  const hasProperAttributes = variations.some((v) => v.attributes.length > 0);

  const variationAttributes = useMemo(() => {
    if (!variations.length || !hasProperAttributes) return [] as { name: string; options: string[] }[];
    const attrMap = new Map<string, Set<string>>();
    for (const v of variations) {
      for (const a of v.attributes) {
        if (!attrMap.has(a.name)) attrMap.set(a.name, new Set());
        attrMap.get(a.name)!.add(a.option);
      }
    }
    return Array.from(attrMap.entries()).map(([name, opts]) => {
      const options = Array.from(opts);
      const nums = options.map((o) => { const m = o.match(/\d+(?:[.,]\d+)?/); return m ? parseFloat(m[0].replace(',', '.')) : NaN; });
      if (nums.every((n) => !Number.isNaN(n))) options.sort((a, b) => nums[options.indexOf(a)] - nums[options.indexOf(b)]);
      return { name, options };
    });
  }, [variations, hasProperAttributes]);

  function doseValue(label: string): number {
    const m = label.replace(',', '.').match(/(\d+(?:\.\d+)?)/);
    return m ? parseFloat(m[1]) : Number.MAX_SAFE_INTEGER;
  }

  function getVariationLabel(v: WcVariation): string {
    if (v.sku) return v.sku;
    if (v.name) return v.name;
    if (v.description) return v.description.replace(/<[^>]*>/g, '').trim();
    const price = v.sale_price || v.price;
    return `Optie - €${parseFloat(price).toFixed(2)}`;
  }

  const [selectedVariationId, setSelectedVariationId] = useState<number | null>(null);
  const [selectedAttrs, setSelectedAttrs] = useState<Record<string, string>>({});

  useEffect(() => {
    if (!product?.id) return;
    const p = product as { id: number; name: string; price?: number | string; salePrice?: number | string; categories?: { name: string }[] };
    trackEcommerce('view_item', [{
      item_id: String(p.id),
      item_name: p.name,
      price: Number(p.salePrice || p.price) || 0,
      quantity: 1,
      ...(p.categories?.[0]?.name ? { item_category: p.categories[0].name } : {}),
    }]);
  }, [product?.id]);

  useEffect(() => {
    setSelectedAttrs({});
    setSelectedVariationId(null);
    setQuantity(1);
    setSelectedImage(0);
  }, [displayProduct?.id]);

  useEffect(() => {
    if (!variations.length) return;
    if (!hasProperAttributes) {
      if (!selectedVariationId) {
        const inStock = variations.filter((v) => v.stock_status === 'instock');
        const pool = inStock.length ? inStock : variations;
        const smallest = [...pool].sort((a, b) => doseValue(getVariationLabel(a)) - doseValue(getVariationLabel(b)))[0];
        setSelectedVariationId(smallest.id);
      }
    } else if (variationAttributes.length > 0 && Object.keys(selectedAttrs).length === 0) {
      // Start with the smallest (in-stock) variation, e.g. 10 mg before 20 mg.
      const inStock = variations.filter((v) => v.stock_status === 'instock');
      const pool = inStock.length ? inStock : variations;
      const key = (v: WcVariation) => v.attributes.map((a) => doseValue(a.option));
      const smallest = [...pool].sort((a, b) => {
        const ka = key(a), kb = key(b);
        for (let i = 0; i < Math.max(ka.length, kb.length); i++) {
          const d = (ka[i] ?? 0) - (kb[i] ?? 0);
          if (d) return d;
        }
        return 0;
      })[0];
      const initial: Record<string, string> = {};
      for (const attr of variationAttributes) initial[attr.name] = attr.options[0] || '';
      for (const a of smallest.attributes) initial[a.name] = a.option;
      setSelectedAttrs(initial);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [variations, variationAttributes, hasProperAttributes]);

  const matchedVariation = useMemo(() => {
    if (!variations.length) return null;
    if (!hasProperAttributes) return variations.find((v) => v.id === selectedVariationId) || null;
    if (!Object.keys(selectedAttrs).length) return null;
    return variations.find((v) => v.attributes.every((a) => selectedAttrs[a.name] === a.option)) || null;
  }, [variations, selectedAttrs, selectedVariationId, hasProperAttributes]);

  // Include the chosen variation (e.g. "10mg") so dose-specific lab tests match.
  const labMatchName = [
    displayProduct?.name ?? '',
    ...(matchedVariation?.attributes?.map((a) => a.option) ?? []),
    ...Object.values(selectedAttrs),
  ].join(' ');

  const labTestsForMatching = useMemo(
    () => (labtests?.tests?.length ? labtests.tests : labTestEntries()),
    [labtests],
  );

  const labTest = useMemo(
    () =>
      displayProduct
        ? matchLabTestForProduct(labTestsForMatching, labMatchName, displayProduct.slug)
        : undefined,
    [displayProduct, labTestsForMatching, labMatchName],
  );

  const effectivePrice = matchedVariation
    ? parseFloat(matchedVariation.regular_price || matchedVariation.price || '0')
    : displayProduct?.price ?? 0;
  const effectiveSalePrice = matchedVariation
    ? (matchedVariation.sale_price ? parseFloat(matchedVariation.sale_price) : undefined)
    : displayProduct?.salePrice;
  const effectiveInStock = matchedVariation
    ? matchedVariation.stock_status === 'instock'
    : displayProduct?.inStock ?? true;
  const effectiveImage = matchedVariation?.image?.src || null;

  useEffect(() => {
    if (!displayProduct || typeof window === 'undefined') return;
    const key = 'recently-viewed';
    const stored: string[] = JSON.parse(localStorage.getItem(key) || '[]');
    const updated = [displayProduct.slug, ...stored.filter((s) => s !== displayProduct.slug)].slice(0, 8);
    localStorage.setItem(key, JSON.stringify(updated));
  }, [displayProduct]);

  const { data: relatedData } = useProducts({ per_page: 4 });

  const navigate = useNavigate();
  const buyBoxRef = useRef<HTMLDivElement | null>(null);
  const [showStickyBar, setShowStickyBar] = useState(false);
  useEffect(() => {
    const onScroll = () => {
      const el = buyBoxRef.current;
      setShowStickyBar(!!el && el.getBoundingClientRect().bottom < 0);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  if (isLoading) {
    return (
      <div className="min-h-screen">
        <div className="container py-8">
          <Skeleton className="h-4 w-64 mb-8" />
          <div className="grid lg:grid-cols-2 gap-12">
            <div>
              <Skeleton className="aspect-square rounded-2xl" />
              <div className="flex gap-3 mt-4">
                {Array.from({ length: 4 }).map((_, i) => <Skeleton key={i} className="w-20 h-20 rounded-xl" />)}
              </div>
            </div>
            <div className="space-y-4">
              <Skeleton className="h-3 w-24" />
              <Skeleton className="h-10 w-3/4" />
              <Skeleton className="h-5 w-32" />
              <Skeleton className="h-12 w-40" />
              <Skeleton className="h-24 w-full" />
              <Skeleton className="h-14 w-full" />
            </div>
          </div>
        </div>
      </div>
    );
  }

  if (!displayProduct) {
    return (
      <div className="container py-20 text-center">
        <h1 className="text-2xl font-bold mb-3">{t('Product niet gevonden', 'Product not found')}</h1>
        <Link to="/shop" className="text-primary font-semibold hover:underline">{t('Terug naar producten', 'Back to products')}</Link>
      </div>
    );
  }

  const galleryImages = displayProduct.images.length > 1 ? displayProduct.images : [displayProduct.image];
  const displayGalleryImages = effectiveImage
    ? [effectiveImage, ...galleryImages.filter((img) => img !== effectiveImage)]
    : galleryImages;

  const related = relatedData?.products
    ? relatedData.products.filter((p) => p.id !== displayProduct.id).slice(0, 4)
    : mockProducts.filter((p) => p.categorySlug === displayProduct.categorySlug && p.id !== displayProduct.id).slice(0, 4);

  const recentSlugs: string[] = typeof window !== 'undefined'
    ? JSON.parse(localStorage.getItem('recently-viewed') || '[]')
    : [];
  const recentlyViewed = recentSlugs
    .filter((s) => s !== displayProduct.slug)
    .map((s) => mockProducts.find((p) => p.slug === s))
    .filter(Boolean)
    .slice(0, 4) as typeof mockProducts;

  const handleAddToCart = async () => {
    try {
      await addItem({
        productId: displayProduct.id,
        variationId: matchedVariation?.id,
        quantity,
      });
      openCart();
    } catch (err) {
      console.error('addToCart failed', err);
      const msg = String((err as Error)?.message || '');
      toast.error(msg.includes('woosb')
        ? t('Deze bundel kan momenteel niet online worden toegevoegd. Neem contact met ons op of probeer het later opnieuw.', 'This bundle cannot be added online right now. Please contact us or try again later.')
        : t('Toevoegen aan winkelwagen mislukt. Probeer het opnieuw.', 'Could not add to cart. Please try again.'));
      // Rethrow so the add-to-cart button returns to its resting state.
      throw err;
    }
  };

  const handleBuyNow = async () => {
    try {
      await addItem({ productId: displayProduct.id, variationId: matchedVariation?.id, quantity });
      navigate({ to: '/checkout' });
    } catch (err) {
      console.error('buyNow failed', err);
      const msg = String((err as Error)?.message || '');
      toast.error(msg.includes('woosb')
        ? t('Deze bundel kan momenteel niet online worden toegevoegd. Neem contact met ons op of probeer het later opnieuw.', 'This bundle cannot be added online right now. Please contact us or try again later.')
        : t('Toevoegen aan winkelwagen mislukt. Probeer het opnieuw.', 'Could not add to cart. Please try again.'));
    }
  };

  const discountPct = effectiveSalePrice ? Math.round((1 - effectiveSalePrice / effectivePrice) * 100) : 0;
  const allAttrsSelected = hasVariations
    ? (hasProperAttributes ? variationAttributes.every((attr) => !!selectedAttrs[attr.name]) : !!selectedVariationId)
    : true;
  const canAddToCart = effectiveInStock && (!hasVariations || (allAttrsSelected && !!matchedVariation));

  return (
    <div className="min-h-screen">
      {/* The same bar as the rest of the site (see components/Breadcrumbs). */}
      <Breadcrumbs
        items={[
          { label: t('Producten', 'Products'), to: '/shop' },
          { label: displayProduct.name },
        ]}
      />

      <section className="container py-10 md:py-14">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-10 lg:gap-16 [&>*]:min-w-0">
          <div className="lg:sticky lg:top-28 lg:self-start">
            <div
              className="relative bg-card border border-border/50 rounded-2xl overflow-hidden aspect-square md:max-lg:aspect-[4/3] cursor-zoom-in group shadow-card"
              onClick={() => setLightboxOpen(true)}
            >
              <img
                src={displayGalleryImages[selectedImage] || displayProduct.image}
                alt={t(`${displayProduct.name} — research peptide productfoto ${selectedImage + 1} van ${displayGalleryImages.length || 1}`, `${displayProduct.name} — research peptide product photo ${selectedImage + 1} of ${displayGalleryImages.length || 1}`)}
                width={800}
                height={800}
                loading="eager"
                decoding="async"
                fetchPriority="high"
                className="w-full h-full object-contain p-8 md:p-12 group-hover:scale-105 transition-transform duration-500"
              />
              <div className="absolute top-4 right-4 p-2.5 rounded-xl bg-background/80 backdrop-blur-sm text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity">
                <ZoomIn className="w-4 h-4" />
              </div>
              {discountPct > 0 && (
                <span className="absolute top-4 left-4 bg-destructive text-destructive-foreground text-xs font-bold px-3 py-1.5 rounded-lg">-{discountPct}%</span>
              )}
              {displayProduct.isNew && (
                <span className={`absolute left-4 bg-primary text-primary-foreground text-xs font-bold px-3 py-1.5 rounded-lg ${discountPct > 0 ? 'top-14' : 'top-4'}`}>{t('Nieuw', 'New')}</span>
              )}
            </div>
            {displayGalleryImages.length > 1 && (
              <div className="flex gap-3 mt-4 overflow-x-auto pb-1">
                {displayGalleryImages.map((img, i) => (
                  <button
                    key={i}
                    onClick={() => setSelectedImage(i)}
                    className={`shrink-0 w-20 h-20 rounded-xl border-2 overflow-hidden transition-all duration-200 ${
                      selectedImage === i ? 'border-primary ring-2 ring-primary/20 shadow-sm' : 'border-border/50 hover:border-primary/40'
                    }`}
                  >
                    <img src={img} alt={`${displayProduct.name} — thumbnail ${i + 1}`} width={80} height={80} loading="lazy" decoding="async" className="w-full h-full object-contain p-2" />
                  </button>
                ))}
              </div>
            )}
          </div>

          <div className="flex flex-col">
            <Link
              to="/product-category/$slug"
              params={{ slug: displayProduct.categorySlug }}
              className="inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-primary hover:underline mb-3 w-fit"
            >
              {displayProduct.category}
            </Link>

            <h1 className="text-3xl md:text-4xl font-black tracking-tight mb-3">{displayProduct.name}</h1>

            {labTest && (
              <a
                href="#lab-test"
                onClick={(e) => {
                  e.preventDefault();
                  document.getElementById('lab-test')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }}
                className="inline-flex items-center gap-1.5 bg-primary text-primary-foreground border border-primary/60 text-xs font-bold px-2.5 py-1 rounded-lg mb-4 w-fit shadow-elevated hover:bg-primary-hover transition-colors focus-ring"
                aria-label={t('Bekijk labtestresultaat', 'View lab test result')}
              >
                <FlaskConical className="w-3.5 h-3.5" aria-hidden="true" />
                {t('Labgetest', 'Lab tested')}
              </a>
            )}

            <div className="flex items-center gap-3 mb-6">
              <StarRating rating={displayProduct.rating} sizeClass="w-4 h-4" />
              <span className="text-sm text-muted-foreground whitespace-nowrap">({displayProduct.reviewCount} {t('beoordelingen', 'reviews')})</span>
              {displayProduct.sku && (
                <span className="hidden sm:inline text-sm text-muted-foreground border-l border-border pl-3">SKU: {matchedVariation?.sku || displayProduct.sku}</span>
              )}
            </div>

            <div className="mb-6 p-5 bg-surface/80 rounded-2xl border border-border/50">
              {effectiveSalePrice ? (
                <div className="flex items-baseline gap-3">
                  <span className="text-4xl font-black text-primary">€{effectiveSalePrice.toFixed(2)}</span>
                  <span className="text-lg text-muted-foreground line-through">€{effectivePrice.toFixed(2)}</span>
                  <span className="ml-auto whitespace-nowrap bg-destructive/10 text-destructive text-xs font-bold px-2.5 py-1 rounded-lg">
                    {t(`Bespaar €${(effectivePrice - effectiveSalePrice).toFixed(2)}`, `Save €${(effectivePrice - effectiveSalePrice).toFixed(2)}`)}
                  </span>
                </div>
              ) : (
                <span className="text-4xl font-black">€{effectivePrice.toFixed(2)}</span>
              )}
            </div>

            {displayProduct.shortDescription && (
              <div
                className="text-muted-foreground mb-6 leading-relaxed text-sm wc-content"
                dangerouslySetInnerHTML={sanitizedHtml(displayProduct.shortDescription)}
              />
            )}

            {hasVariations && variations.length > 0 && !hasProperAttributes && (
              <div className="space-y-4 mb-6">
                <label className="block text-sm font-semibold mb-2">{t('Kies een optie', 'Choose an option')}</label>
                <div className="flex flex-col gap-2">
                  {variations.map((v) => {
                    const isSelected = selectedVariationId === v.id;
                    const vPrice = v.sale_price ? parseFloat(v.sale_price) : parseFloat(v.price);
                    const vRegular = parseFloat(v.regular_price || v.price);
                    const label = getVariationLabel(v);
                    const unavailable = v.stock_status !== 'instock';
                    return (
                      <button
                        key={v.id}
                        disabled={unavailable}
                        aria-disabled={unavailable}
                        onClick={() => { if (unavailable) return; setSelectedVariationId(v.id); setSelectedImage(0); }}
                        className={`flex items-center justify-between px-4 py-3 text-sm font-medium rounded-xl border-2 transition-all duration-200 text-left ${
                          unavailable
                            ? 'border-border bg-muted/40 text-muted-foreground opacity-50 cursor-not-allowed line-through'
                            : isSelected
                              ? 'border-primary bg-primary/10 text-primary shadow-sm'
                              : 'border-border hover:border-primary/40 text-foreground'
                        }`}
                      >
                        <span className="flex items-center gap-2">
                          {v.image?.src && (
                            <img src={v.image.src} alt={`${displayProduct.name} variant ${label}${unavailable ? t(' (niet beschikbaar)', ' (unavailable)') : ''}`} width={40} height={40} loading="lazy" decoding="async" className={`w-10 h-10 object-contain rounded-lg bg-card ${unavailable ? 'grayscale' : ''}`} />
                          )}
                          <span>{label}</span>
                        </span>
                        <span className="flex items-center gap-2 shrink-0">
                          {v.sale_price && vRegular > vPrice && (
                            <span className="text-muted-foreground line-through text-xs">€{vRegular.toFixed(2)}</span>
                          )}
                          <span className="font-bold">€{vPrice.toFixed(2)}</span>
                          {unavailable && (
                            <span className="text-xs text-destructive no-underline">({t('Uitverkocht', 'Sold out')})</span>
                          )}
                        </span>
                      </button>
                    );
                  })}
                </div>
              </div>
            )}
            {hasVariations && hasProperAttributes && variationAttributes.length > 0 && (
              <div className="space-y-4 mb-6">
                {variationAttributes.map((attr) => (
                  <div key={attr.name}>
                    <label className="block text-sm font-semibold mb-2">{attr.name}</label>
                    <div className="flex flex-wrap gap-2">
                      {attr.options.map((option) => {
                        const isSelected = selectedAttrs[attr.name] === option;
                        // An option is available if some variation matches it + other currently-selected attrs and is in stock
                        const isAvailable = variations.some((v) => {
                          if (v.stock_status !== 'instock') return false;
                          return v.attributes.every((a) => {
                            if (a.name === attr.name) return a.option === option;
                            const sel = selectedAttrs[a.name];
                            return !sel || sel === a.option;
                          });
                        });
                        return (
                          <button
                            key={option}
                            disabled={!isAvailable}
                            aria-disabled={!isAvailable}
                            title={!isAvailable ? t('Niet beschikbaar', 'Not available') : undefined}
                            onClick={() => { if (!isAvailable) return; setSelectedAttrs((prev) => ({ ...prev, [attr.name]: option })); setSelectedImage(0); }}
                            className={`px-4 py-2 text-sm font-medium rounded-xl border-2 transition-all duration-200 ${
                              !isAvailable
                                ? 'border-border bg-muted/40 text-muted-foreground opacity-50 cursor-not-allowed line-through'
                                : isSelected
                                  ? 'border-primary bg-primary/10 text-primary shadow-sm'
                                  : 'border-border hover:border-primary/40 text-foreground'
                            }`}
                          >
                            {option}
                          </button>
                        );
                      })}
                    </div>
                  </div>
                ))}
                {allAttrsSelected && !matchedVariation && (
                  <p className="text-sm text-destructive font-medium">{t('Deze combinatie is niet beschikbaar.', 'This combination is not available.')}</p>
                )}
              </div>
            )}

            {bundleItems && bundleItems.length > 0 && (
              <div className="mb-5 rounded-2xl border border-border bg-card px-4 py-3">
                <p className="text-sm font-semibold mb-1">{t('Inhoud van deze bundel', 'This bundle contains')}</p>
                <ul className="divide-y divide-border/60">
                  {bundleItems.map((b) => (
                    <li key={b.id}>
                      <Link to="/product/$slug" params={{ slug: b.slug }} className="flex items-center gap-3 py-2 hover:text-primary transition-colors">
                        <img src={b.image} alt={b.name} width={40} height={40} loading="lazy" className="w-10 h-10 object-cover rounded-md bg-background" />
                        <span className="flex-1 text-sm font-medium">{b.qty > 1 ? `${b.qty}× ` : ''}{b.name}</span>
                        <span className="text-xs text-muted-foreground">€{b.price.toFixed(2)}</span>
                      </Link>
                    </li>
                  ))}
                </ul>
              </div>
            )}

            <div className="flex items-center gap-2 mb-6">
              {effectiveInStock ? (
                <div className="inline-flex items-center gap-1.5 bg-success/10 text-success text-sm font-semibold px-3 py-1.5 rounded-lg">
                  <Check className="w-3.5 h-3.5" /> {t('Op voorraad', 'In stock')}
                </div>
              ) : (
                <div className="inline-flex items-center gap-1.5 bg-destructive/10 text-destructive text-sm font-semibold px-3 py-1.5 rounded-lg">
                  <X className="w-3.5 h-3.5" /> {t('Uitverkocht', 'Sold out')}
                </div>
              )}
            </div>

            {canAddToCart && (
              <div ref={buyBoxRef} className="mb-8 space-y-3">
                <div className="flex items-center gap-3">
                  <div className="flex items-center border border-border rounded-xl bg-card shrink-0">
                    <button onClick={() => setQuantity(Math.max(1, quantity - 1))} aria-label={t('Minder', 'Less')} className="p-3 hover:bg-muted transition-colors rounded-l-xl">
                      <Minus className="w-4 h-4" />
                    </button>
                    {/* Keyed re-mount per value: the number flips up as it changes, so the quantity action feels registered. */}
                    <AnimatePresence mode="popLayout" initial={false}>
                      <motion.span
                        key={quantity}
                        initial={{ opacity: 0, y: 8 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: -8 }}
                        transition={{ duration: 0.15, ease: 'easeOut' }}
                        className="w-10 text-center font-bold text-sm"
                      >
                        {quantity}
                      </motion.span>
                    </AnimatePresence>
                    <button onClick={() => setQuantity(quantity + 1)} aria-label={t('Meer', 'More')} className="p-3 hover:bg-muted transition-colors rounded-r-xl">
                      <Plus className="w-4 h-4" />
                    </button>
                  </div>
                  <AddToCartButton
                    onAdd={handleAddToCart}
                    label={t('In Winkelwagen', 'Add to Cart')}
                    pendingLabel={t('Toevoegen…', 'Adding…')}
                    addedLabel={t('Toegevoegd', 'Added')}
                    className="flex-1 min-w-0 hover:shadow-glow"
                  />
                </div>
                <button
                  onClick={handleBuyNow}
                  disabled={addPending}
                  className="w-full flex items-center justify-center gap-2 rounded-xl border-2 border-primary text-primary font-bold py-3 text-sm uppercase tracking-wide hover:bg-primary/10 transition-colors disabled:opacity-60"
                >
                  {t('Direct afrekenen', 'Buy now')} <ChevronRight className="w-4 h-4" />
                </button>
              </div>
            )}

            <div className="grid grid-cols-3 gap-3 mt-auto">
              {[
                { icon: Truck, label: t('Gratis verzending', 'Free shipping'), sub: t('Vanaf €150', 'From €150') },
                { icon: Shield, label: t('Discreet verpakt', 'Discreetly packaged'), sub: t('100% anoniem', '100% anonymous') },
                { icon: RotateCcw, label: t('Snelle levering', 'Fast delivery'), sub: t('1-3 werkdagen (NL)', '1-3 business days (NL)'), tooltip: true },
              ].map((badge) => (
                <div key={badge.label} className="flex flex-col items-center text-center p-3 bg-card rounded-xl border border-border/50 relative">
                  <badge.icon className="w-5 h-5 text-primary mb-1.5" />
                  <span className="text-[11px] font-semibold leading-tight">{badge.label}</span>
                  <span className="text-[10px] text-muted-foreground">{badge.sub}</span>
                  {'tooltip' in badge && badge.tooltip && (
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <button className="absolute top-1.5 right-1.5 text-muted-foreground hover:text-primary transition-colors">
                          <Info className="w-3 h-3" />
                        </button>
                      </TooltipTrigger>
                      <TooltipContent side="top" className="max-w-[200px] text-xs">
                        <p className="font-semibold mb-1">{t('Geschatte levertijden:', 'Estimated delivery times:')}</p>
                        <ul className="space-y-0.5">
                          <li>🇳🇱 {t('Nederland: 1-3 werkdagen', 'Netherlands: 1-3 business days')}</li>
                          <li>🇧🇪 {t('België: 2-5 werkdagen', 'Belgium: 2-5 business days')}</li>
                          <li>🇩🇪 {t('Duitsland: 3-6 werkdagen', 'Germany: 3-6 business days')}</li>
                          <li>🇪🇺 {t('Overig EU: 3-7 werkdagen', 'Rest of EU: 3-7 business days')}</li>
                        </ul>
                      </TooltipContent>
                    </Tooltip>
                  )}
                </div>
              ))}
            </div>

            <div className="mt-6">
              <ShippingEstimate />
            </div>

            {displayProduct.attributes && displayProduct.attributes.length > 0 && !hasVariations && (
              <div className="border-t border-border/50 pt-5 mt-6 space-y-2">
                {displayProduct.attributes.map((attr) => (
                  <div key={attr.name} className="flex text-sm">
                    <span className="text-muted-foreground w-36 shrink-0">{attr.name}:</span>
                    <span className="font-medium">{attr.value}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </section>

      {(() => {
        if (!labTest) return null;
        return (
          <section id="lab-test" className="border-t border-border/50 bg-primary/5 scroll-mt-24">
            <div className="container py-6 md:py-8">
              <div className="flex flex-col sm:flex-row items-start sm:items-center gap-4 sm:gap-6 bg-card border border-primary/20 rounded-2xl p-5 md:p-6 shadow-card">
                <div className="w-12 h-12 rounded-xl gradient-primary flex items-center justify-center shrink-0 shadow-sm">
                  <FlaskConical className="w-6 h-6 text-white" />
                </div>
                <div className="flex-1 min-w-0">
                  <h3 className="font-bold text-sm mb-1 flex items-center gap-2">
                    <Check className="w-4 h-4 text-primary" />
                    {t('Onafhankelijk lab-getest product', 'Independently lab-tested product')}
                  </h3>
                  <p className="text-xs text-muted-foreground leading-relaxed">
                    {t('Dit product is getest door', 'This product was tested by')} <span className="font-semibold text-foreground">Janoshik</span> {t('op', 'on')} {labTest.date} {t('met als resultaat:', 'with the result:')} <span className="font-semibold text-primary">{labResultText(labTest.result, t('nl', 'en') as 'nl' | 'en')}</span>
                  </p>
                </div>
                <div className="flex gap-2 shrink-0">
                  {labTest.url !== '#' && (
                    <a
                      href={labTest.url}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="inline-flex items-center gap-1.5 text-xs font-semibold text-primary hover:underline bg-primary/10 hover:bg-primary/15 px-4 py-2.5 rounded-xl transition-colors"
                    >
                      {t('Bekijk rapport', 'View report')} <ExternalLink className="w-3.5 h-3.5" />
                    </a>
                  )}
                  <Link
                    to="/labtesten"
                    className="inline-flex items-center gap-1.5 text-xs font-semibold text-muted-foreground hover:text-foreground bg-muted/50 hover:bg-muted px-4 py-2.5 rounded-xl transition-colors"
                  >
                    {t('Alle labtesten', 'All lab tests')} <ChevronRight className="w-3.5 h-3.5" />
                  </Link>
                </div>
              </div>
            </div>
          </section>
        );
      })()}

      <section className="bg-surface/50 border-t border-border/50">
        <div className="container py-12 md:py-16">
          <div className="flex gap-1 mb-8 bg-card rounded-xl border border-border/50 p-1.5 w-full sm:w-fit max-w-full overflow-x-auto [&>button]:shrink-0 [&>button]:whitespace-nowrap">
            {[
              { key: 'description' as const, label: t('Beschrijving', 'Description') },
              { key: 'info' as const, label: t('Extra Informatie', 'Additional Information') },
              { key: 'reviews' as const, label: t(`Beoordelingen (${displayProduct.reviewCount})`, `Reviews (${displayProduct.reviewCount})`) },
            ].map((tab) => (
              <button
                key={tab.key}
                onClick={() => setActiveTab(tab.key)}
                className={`px-5 py-2.5 text-sm font-semibold rounded-lg transition-all duration-200 ${
                  activeTab === tab.key
                    ? 'gradient-primary text-white shadow-sm'
                    : 'text-muted-foreground hover:text-foreground hover:bg-muted/50'
                }`}
              >
                {tab.label}
              </button>
            ))}
          </div>

          <div className="bg-card rounded-2xl border border-border/50 shadow-card p-6 md:p-10">
            {activeTab === 'description' && (
              <div
                className="wc-content prose prose-sm md:prose-base max-w-none
                  prose-headings:text-foreground prose-headings:font-bold prose-headings:tracking-tight
                  prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4
                  prose-h3:text-xl prose-h3:mt-6 prose-h3:mb-3
                  prose-h4:text-lg prose-h4:mt-5 prose-h4:mb-2
                  prose-p:text-foreground/80 prose-p:leading-relaxed prose-p:mb-4
                  prose-strong:text-foreground prose-strong:font-bold
                  prose-ul:my-4 prose-ul:pl-6 prose-ul:list-disc
                  prose-ol:my-4 prose-ol:pl-6 prose-ol:list-decimal
                  prose-li:text-foreground/80 prose-li:mb-1.5 prose-li:leading-relaxed
                  prose-a:text-primary prose-a:font-medium prose-a:no-underline hover:prose-a:underline
                  prose-table:border-collapse prose-table:w-full prose-table:my-6
                  prose-th:bg-surface prose-th:text-foreground prose-th:font-semibold prose-th:text-left prose-th:px-4 prose-th:py-3 prose-th:border prose-th:border-border
                  prose-td:px-4 prose-td:py-3 prose-td:border prose-td:border-border prose-td:text-foreground/80
                  prose-img:rounded-xl prose-img:my-6 prose-img:shadow-card
                  prose-blockquote:border-l-4 prose-blockquote:border-primary prose-blockquote:bg-surface/50 prose-blockquote:px-6 prose-blockquote:py-4 prose-blockquote:rounded-r-xl prose-blockquote:italic prose-blockquote:text-foreground/70"
                dangerouslySetInnerHTML={sanitizedHtml(displayProduct.description)}
              />
            )}
            {activeTab === 'info' && displayProduct.attributes && displayProduct.attributes.length > 0 && (
              <table className="w-full text-sm">
                <tbody>
                  {displayProduct.attributes.map((attr, i) => (
                    <tr key={attr.name} className={i < displayProduct.attributes!.length - 1 ? 'border-b border-border/50' : ''}>
                      <td className="py-4 text-muted-foreground w-48 font-medium">{attr.name}</td>
                      <td className="py-4 font-semibold">{attr.value}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
            {activeTab === 'reviews' && (
              <div className="space-y-6">
                {(() => {
                  const counts = [0, 0, 0, 0, 0];
                  for (const r of reviews) {
                    const s = Math.round(r.rating);
                    if (s >= 1 && s <= 5) counts[s - 1]++;
                  }
                  const totalReviews = reviews.length;
                  return (
                    <div className="flex flex-col sm:flex-row items-center sm:items-stretch gap-6 p-6 bg-surface/80 rounded-2xl border border-border/50">
                      <div className="text-center sm:border-r sm:border-border/50 sm:pr-6">
                        <p className="text-4xl font-black text-primary">{displayProduct.rating.toFixed(1)}</p>
                        <div className="mt-2 flex justify-center">
                          <StarRating rating={displayProduct.rating} sizeClass="w-4 h-4" />
                        </div>
                        <p className="text-xs text-muted-foreground mt-1.5">
                          {displayProduct.reviewCount} {displayProduct.reviewCount === 1 ? t('beoordeling', 'review') : t('beoordelingen', 'reviews')}
                        </p>
                      </div>
                      <div className="flex-1 space-y-1.5 w-full">
                        {[5, 4, 3, 2, 1].map((stars) => {
                          const count = counts[stars - 1];
                          const pct = totalReviews > 0 ? Math.round((count / totalReviews) * 100) : 0;
                          return (
                            <div key={stars} className="flex items-center gap-2 text-xs">
                              <span className="w-3 font-medium">{stars}</span>
                              <Star className="w-3 h-3 fill-warning text-warning" />
                              <div className="flex-1 h-2.5 bg-muted rounded-full overflow-hidden">
                                <div className="h-full bg-warning rounded-full transition-all" style={{ width: `${pct}%` }} />
                              </div>
                              <span className="w-10 text-muted-foreground text-right">{pct}%</span>
                            </div>
                          );
                        })}
                      </div>
                    </div>
                  );
                })()}

                {reviewsLoading ? (
                  <div className="space-y-4">
                    {Array.from({ length: 3 }).map((_, i) => (
                      <div key={i} className="p-5 bg-card border border-border/50 rounded-2xl">
                        <Skeleton className="h-4 w-32 mb-2" />
                        <Skeleton className="h-3 w-24 mb-3" />
                        <Skeleton className="h-4 w-full mb-1" />
                        <Skeleton className="h-4 w-5/6" />
                      </div>
                    ))}
                  </div>
                ) : reviews.length === 0 ? (
                  <div className="text-center py-10 px-6 bg-card border border-border/50 rounded-2xl">
                    <p className="text-sm text-muted-foreground">
                      {t('Er zijn nog geen beoordelingen voor dit product. Wees de eerste die een review achterlaat!', 'There are no reviews for this product yet. Be the first to leave a review!')}
                    </p>
                  </div>
                ) : (
                  <ul className="space-y-4">
                    {reviews.map((r) => (
                      <li key={r.id} className="p-5 bg-card border border-border/50 rounded-2xl">
                        <div className="flex items-center justify-between gap-3 mb-2 flex-wrap">
                          <div className="flex items-center gap-3">
                            <span className="font-semibold text-sm">{r.reviewer || t('Klant', 'Customer')}</span>
                            {r.verified && (
                              <span className="inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider text-primary bg-primary/10 px-2 py-0.5 rounded-full">
                                <Check className="w-3 h-3" /> {t('Geverifieerde aankoop', 'Verified purchase')}
                              </span>
                            )}
                          </div>
                          <time className="text-xs text-muted-foreground" dateTime={r.date_created}>
                            {new Date(r.date_created).toLocaleDateString(locale(useLang()), { year: 'numeric', month: 'long', day: 'numeric' })}
                          </time>
                        </div>
                        <StarRating rating={r.rating} sizeClass="w-3.5 h-3.5" className="mb-2" />
                        <div
                          className="text-sm text-muted-foreground leading-relaxed prose prose-sm max-w-none dark:prose-invert"
                          dangerouslySetInnerHTML={sanitizedHtml(r.review || '')}
                        />
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            )}
          </div>
        </div>
      </section>

      <ProductAssistant context={displayProduct.name} />
      <nav aria-label={t('Meer over dit product', 'More about this product')} className="container pb-4">
        <h2 className="text-xl font-bold mb-4">{t(`Meer over ${displayProduct.name}`, `More about ${displayProduct.name}`)}</h2>
        <ul className="flex flex-wrap gap-2 text-sm">
          <li><Link to="/product-category/$slug" params={{ slug: displayProduct.categorySlug }} className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t(`Meer ${displayProduct.category}`, `More ${displayProduct.category}`)}</Link></li>
          <li><Link to="/labtesten" className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t('Labresultaten bekijken', 'View lab results')}</Link></li>
          <li><Link to="/peptide-calculator" className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t('Peptide calculator', 'Peptide calculator')}</Link></li>
          <li><Link to="/blog" className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t('Kennisbank & blog', 'Knowledge base & blog')}</Link></li>
          <li><Link to="/veelgestelde-vragen" className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t('Veelgestelde vragen', 'Frequently asked questions')}</Link></li>
          <li><Link to="/retourbeleid" className="inline-block rounded-full border border-border px-4 py-2 hover:border-primary hover:text-primary transition-colors">{t('Verzending & retour', 'Shipping & returns')}</Link></li>
        </ul>
      </nav>

      {related.length > 0 && (
        <section className="container py-16">
          <div className="flex items-center justify-between mb-10">
            <h2 className="text-3xl font-black">{t('Gerelateerde Producten', 'Related Products')}</h2>
            <Link to="/shop" className="text-sm text-primary font-semibold hover:underline flex items-center gap-1 group">
              {t('Bekijk alles', 'View all')} <ChevronRight className="w-4 h-4 group-hover:translate-x-0.5 transition-transform" />
            </Link>
          </div>
          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-5">
            {related.map((p) => <ProductCard key={p.id} product={p} />)}
          </div>
        </section>
      )}

      {recentlyViewed.length > 0 && (
        <section className="bg-surface/50 border-t border-border/50">
          <div className="container py-16">
            <h2 className="text-3xl font-black mb-10">{t('Recent Bekeken', 'Recently Viewed')}</h2>
            <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-5">
              {recentlyViewed.map((p) => <ProductCard key={p.id} product={p} />)}
            </div>
          </div>
        </section>
      )}

      {lightboxOpen && (
        <div
          className="fixed inset-0 z-50 bg-background/95 backdrop-blur-sm flex items-center justify-center p-4"
          onClick={() => setLightboxOpen(false)}
        >
          <button className="absolute top-6 right-6 p-2.5 rounded-xl bg-card border border-border text-foreground hover:text-primary transition-colors" onClick={() => setLightboxOpen(false)}>
            <X className="w-5 h-5" />
          </button>
          <img
            src={displayGalleryImages[selectedImage] || displayProduct.image}
            alt={t(`${displayProduct.name} — vergrote weergave`, `${displayProduct.name} — enlarged view`)}
            width={1600}
            height={1600}
            decoding="async"
            className="max-w-full max-h-[85vh] object-contain"
            onClick={(e) => e.stopPropagation()}
          />
        </div>
      )}

      {canAddToCart && (
        <div
          className={`lg:hidden fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/95 backdrop-blur px-4 py-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] transition-transform duration-300 ${showStickyBar ? 'translate-y-0' : 'translate-y-full'}`}
          aria-hidden={!showStickyBar}
        >
          <div className="flex items-center gap-3">
            <div className="min-w-0 flex-1">
              <p className="truncate text-xs text-muted-foreground">{displayProduct.name}</p>
              <p className="text-lg font-black text-primary">€{(effectiveSalePrice ?? effectivePrice).toFixed(2)}</p>
            </div>
            <AddToCartButton
              size="inline"
              onAdd={handleAddToCart}
              label={t('Bestellen', 'Order now')}
              pendingLabel={t('Bezig…', 'Working…')}
              addedLabel={t('Toegevoegd', 'Added')}
              disabled={!showStickyBar}
            />
          </div>
        </div>
      )}
    </div>
  );
}
