'use client';

/**
 * CMS Product Slider — mirrors cms-element-product-slider.html.twig
 *
 * Pixel-based infinite slider using the clone technique.
 * visibleCount: 3 on desktop (≥1024), 2 on tablet (≥640), 1 on mobile.
 * Clones before/after real items allow seamless wrap-around.
 */

import { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { getProductUrl } from '@/lib/shopware-api';
import WishlistButton from '@/components/product/WishlistButton';
import { useCart } from '@/lib/cart-context';
import { useSalesChannel } from '@/lib/sales-channel-context';
import type { CmsSlot } from '@/components/cms/types';

const GAP = 30;

// ── Slider product card ───────────────────────────────────────────────────────
function SliderCard({ product }: { product: any }) {
  const name        = product.translated?.name || product.name || '';
  const price       = product.calculatedPrice?.unitPrice || product.price?.[0]?.gross || 0;
  const listPrice   = product.calculatedPrice?.listPrice?.price;
  const hasDiscount = listPrice && listPrice > price;
  const imageUrl    = product.cover?.media?.url;
  const { localizeHref, formatPrice } = useSalesChannel();
  const href        = localizeHref(getProductUrl(product));

  const rawDesc: string = product.translated?.description || product.description || '';
  const shortDesc = rawDesc.replace(/<[^>]*>/g, '').trim();

  const properties: string[] = (product.properties ?? []).map((p: any) => {
    const g = p.group?.translated?.name || p.group?.name || '';
    const v = p.translated?.name || p.name || '';
    return g && v ? `${g}: ${v}` : v;
  }).filter(Boolean);

  const { addToCart } = useCart();
  const [adding, setAdding] = useState(false);
  const [added,  setAdded]  = useState(false);

  const handleAdd = async (e: React.MouseEvent) => {
    e.preventDefault(); e.stopPropagation();
    if (adding) return;
    setAdding(true);
    try { await addToCart(product.id, 1); setAdded(true); setTimeout(() => setAdded(false), 2000); }
    catch { /* ignore */ } finally { setAdding(false); }
  };

  return (
    <div className="flex flex-col h-full border border-surface-200 rounded-xl overflow-hidden bg-white group">
      <Link href={href} className="relative block bg-surface-50 aspect-square overflow-hidden flex-shrink-0">
        {imageUrl
          ? <Image src={imageUrl} alt={name} fill sizes="33vw" className="object-contain p-4 group-hover:scale-105 transition-transform duration-300" />
          : <div className="w-full h-full flex items-center justify-center text-surface-300 text-5xl">📦</div>
        }
        {hasDiscount && <span className="absolute top-3 left-3 bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-md">Sale</span>}
        <WishlistButton productId={product.id} variant="card" />
      </Link>

      <div className="flex flex-col flex-1 p-4 gap-1.5">
        {properties.length > 0 && (
          <p className="text-xs text-surface-500 leading-tight">
            {properties.map((p, i) => (
              <span key={i}>
                {i > 0 && <span className="mx-1 text-surface-300">|</span>}
                {p.includes(':')
                  ? <><span className="text-surface-400">{p.split(':')[0]}:</span><strong className="ml-1 font-semibold text-surface-700">{p.split(':').slice(1).join(':').trim()}</strong></>
                  : p}
              </span>
            ))}
          </p>
        )}
        <Link href={href}>
          <h3 className="font-semibold text-surface-900 leading-snug group-hover:text-brand-600 transition-colors line-clamp-2">{name}</h3>
        </Link>
        {shortDesc && <p className="text-sm text-surface-500 leading-relaxed line-clamp-3 flex-1">{shortDesc}</p>}
        <div className="flex items-baseline gap-1 mt-auto pt-2">
          <span className="font-bold text-lg text-surface-900">{formatPrice(price)}</span>
          {hasDiscount && <span className="text-sm text-surface-400 line-through">{formatPrice(listPrice)}</span>}
          <span className="text-xs text-surface-400">*</span>
        </div>
      </div>

      <div className="px-4 pb-4">
        <button onClick={handleAdd} disabled={adding}
          className={`w-full py-3 rounded-lg text-sm font-semibold flex items-center justify-center gap-2 transition-all active:scale-[0.98] disabled:opacity-50 ${added ? 'bg-green-500 text-white' : 'bg-brand-600 hover:bg-brand-700 text-white'}`}
        >
          {adding ? <><svg className="w-4 h-4 animate-spin" viewBox="0 0 24 24" fill="none"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>Adding…</>
          : added  ? <><svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7"/></svg>Added!</>
          : <><svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}><path strokeLinecap="round" strokeLinejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/></svg>Add to shopping cart</>}
        </button>
      </div>
    </div>
  );
}

const ChevL = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"/></svg>;
const ChevR = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>;

// ── Main component ────────────────────────────────────────────────────────────
export default function CmsElementProductSlider({ slot }: { slot: CmsSlot }) {
  const cfg = slot.config ?? {};
  const navArrows      = cfg.navigationArrows?.value ?? 'outside';
  const autoplay       = cfg.rotate?.value            ?? false;
  const autoplayMs     = Number(cfg.autoplayTimeout?.value ?? 5000);
  const speedMs        = Number(cfg.speed?.value      ?? 300);
  const border         = cfg.border?.value            ?? false;
  const elMinWidth     = Number(cfg.elMinWidth?.value ?? 300) || 300;
  const title          = cfg.title?.value             ?? '';

  const rawProducts = slot.data?.products;
  const realItems: any[] = Array.isArray(rawProducts) ? rawProducts : (rawProducts?.elements ?? []);
  const n = realItems.length;

  // ── Responsive visible count ──────────────────────────────────────────────
  const [vc, setVc] = useState(3); // 3 = desktop default (SSR safe)

  const computeVc = useCallback(() => {
    const w = window.innerWidth;
    if (w < 640)  return 1;
    if (w < 1024) return 2;
    return 3;
  }, []);

  // useLayoutEffect: fires before first browser paint → no visible flash
  useLayoutEffect(() => { setVc(computeVc()); }, [computeVc]);
  useEffect(() => {
    const h = () => setVc(computeVc());
    window.addEventListener('resize', h);
    return () => window.removeEventListener('resize', h);
  }, [computeVc]);

  // ── Container measurement ─────────────────────────────────────────────────
  const viewportRef = useRef<HTMLDivElement>(null);
  const [containerW, setContainerW] = useState(0);

  useLayoutEffect(() => {
    const el = viewportRef.current;
    if (!el) return;
    const measure = () => { const w = el.offsetWidth; if (w > 0) setContainerW(w); };
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(el);
    return () => ro.disconnect();
  }, []);

  // ── Derived geometry ──────────────────────────────────────────────────────
  const cardW  = containerW > 0 ? (containerW - (vc - 1) * GAP) / vc : 0;
  const stepPx = cardW + GAP;                      // pixels per slide step

  // Clone technique: [vc clones before | real | vc clones after]
  const canLoop = n > vc;
  const cloneN  = canLoop ? vc : 0;
  const allItems = canLoop
    ? [...realItems.slice(-cloneN), ...realItems, ...realItems.slice(0, cloneN)]
    : realItems;
  const total = allItems.length;

  // ── Slider state ──────────────────────────────────────────────────────────
  const [realIdx,  setRealIdx]  = useState(0);
  const [pos,      setPos]      = useState(cloneN);
  const [animated, setAnimated] = useState(false); // start false — enable after layout

  // Stable refs
  const posRef     = useRef(pos);     posRef.current     = pos;
  const realRef    = useRef(realIdx); realRef.current    = realIdx;
  const cloneRef   = useRef(cloneN);  cloneRef.current   = cloneN;
  const nRef       = useRef(n);       nRef.current       = n;
  const vcRef      = useRef(vc);      vcRef.current      = vc;
  const loopRef    = useRef(canLoop); loopRef.current    = canLoop;
  const stepRef    = useRef(stepPx);  stepRef.current    = stepPx;

  // Re-sync pos when vc or container changes (before paint)
  const prevVc     = useRef(vc);
  const prevCloneN = useRef(cloneN);
  useLayoutEffect(() => {
    const newClone = n > vc ? vc : 0;
    if (prevVc.current === vc && prevCloneN.current === newClone) return;
    prevVc.current     = vc;
    prevCloneN.current = newClone;
    setAnimated(false);
    setPos(newClone + realRef.current);
  }, [vc, n]);

  // Enable animation once geometry is known — double rAF so the initial
  // translateX position renders without transition before we switch it on.
  useLayoutEffect(() => {
    if (cardW <= 0) return;
    const id = requestAnimationFrame(() => requestAnimationFrame(() => setAnimated(true)));
    return () => cancelAnimationFrame(id);
  }, [cardW]);

  // Re-enable animation after snap (two rAF ticks)
  useEffect(() => {
    if (animated) return;
    const id = requestAnimationFrame(() => requestAnimationFrame(() => setAnimated(true)));
    return () => cancelAnimationFrame(id);
  }, [animated]);

  // Snap-back after clone zone
  const onTransitionEnd = useCallback(() => {
    if (!loopRef.current) return;
    const p = posRef.current, cn = cloneRef.current, c = nRef.current;
    if (p < cn) { setAnimated(false); setPos(p + c); }
    else if (p >= cn + c) { setAnimated(false); setPos(p - c); }
  }, []);

  // ── Navigation ────────────────────────────────────────────────────────────
  const prev = useCallback(() => {
    const nr = realRef.current - 1;
    setRealIdx(((nr % nRef.current) + nRef.current) % nRef.current);
    setAnimated(true);
    setPos(loopRef.current ? cloneRef.current + nr : (p: number) => Math.max(0, p - 1) as any);
  }, []);

  const next = useCallback(() => {
    const nr = realRef.current + 1;
    setRealIdx(nr % nRef.current);
    setAnimated(true);
    setPos(loopRef.current ? cloneRef.current + nr : (p: number) => Math.min(p + 1, nRef.current - vcRef.current) as any);
  }, []);

  const goTo = useCallback((i: number) => {
    setRealIdx(i);
    setAnimated(true);
    setPos(cloneRef.current + i);
  }, []);

  // Autoplay
  useEffect(() => {
    if (!autoplay) return;
    const t = setInterval(next, autoplayMs);
    return () => clearInterval(t);
  }, [autoplay, autoplayMs, next]);

  if (n === 0) return null;

  // ── Render ────────────────────────────────────────────────────────────────
  const showArrows = navArrows !== 'none';
  const arrowOut   = navArrows === 'outside';
  const atStart    = !canLoop && pos === 0;
  const atEnd      = !canLoop && pos >= n - vc;

  const translateX = -(pos * stepPx);

  const arrowCls = 'absolute top-1/2 -translate-y-1/2 z-10 w-9 h-9 rounded-full bg-white shadow border border-surface-200 text-surface-700 hover:bg-surface-50 flex items-center justify-center transition disabled:opacity-30';

  return (
    <div className="w-full">
      {title && <h2 className="text-2xl font-bold mb-6">{title}</h2>}

      <div className={['relative w-full', border ? 'border border-surface-200 rounded-xl p-4' : ''].filter(Boolean).join(' ')}>
        <div className={arrowOut && showArrows ? 'px-10' : ''}>

          {/* Overflow viewport */}
          <div ref={viewportRef} className="overflow-hidden w-full">
            <div
              style={{
                display: 'flex',
                width: '100%',
                gap: `${GAP}px`,
                transform: `translateX(${translateX}px)`,
                transition: animated ? `transform ${speedMs}ms ease` : 'none',
                willChange: 'transform',
              }}
              onTransitionEnd={onTransitionEnd}
            >
              {allItems.map((p: any, i) => (
                <div key={i} style={{ flex: `0 0 ${cardW > 0 ? cardW + 'px' : `calc((100% - ${(vc-1)*GAP}px) / ${vc})`}`, minWidth: 0 }}>
                  <SliderCard product={p} />
                </div>
              ))}
            </div>
          </div>

          {showArrows && !arrowOut && (
            <>
              <button onClick={prev} disabled={atStart} aria-label="Previous" className={`${arrowCls} left-2`}><ChevL /></button>
              <button onClick={next} disabled={atEnd}   aria-label="Next"     className={`${arrowCls} right-2`}><ChevR /></button>
            </>
          )}
        </div>

        {showArrows && arrowOut && (
          <>
            <button onClick={prev} disabled={atStart} aria-label="Previous" className={`${arrowCls} left-0`}><ChevL /></button>
            <button onClick={next} disabled={atEnd}   aria-label="Next"     className={`${arrowCls} right-0`}><ChevR /></button>
          </>
        )}
      </div>

      {n > 1 && (
        <div className="flex justify-center gap-1.5 mt-4">
          {realItems.map((_, i) => (
            <button key={i} onClick={() => goTo(i)} aria-label={`Slide ${i + 1}`}
              className={`w-2 h-2 rounded-full transition-colors ${i === realIdx ? 'bg-surface-900' : 'bg-surface-300'}`}
            />
          ))}
        </div>
      )}
    </div>
  );
}
