"use client";

import Image from "next/image";
import Link from "next/link";
import { useCallback, useEffect, useRef, useState, type TouchEvent } from "react";
import { ArrowLeftSmallIcon, ArrowRightSmallIcon } from "@/components/ui/Icons";
import { useMediaQuery } from "@/hooks/useMediaQuery";
import { cn } from "@/lib/cn";
import { membershipCards } from "@/data/benefits";

const SWIPE_THRESHOLD_PX = 40;
const GAP_PX = 24;
const REAL_COUNT = membershipCards.length;
// Rendered twice so the track can keep sliding forward and silently snap back.
const trackItems = [...membershipCards, ...membershipCards];

const navButton =
  "absolute top-1/2 z-10 flex size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full border border-black/12 bg-white text-[#333] shadow-[0_4px_12px_rgba(0,0,0,0.08)] transition-[background-color,transform,box-shadow,opacity] duration-200 hover:scale-[1.08] hover:shadow-[0_6px_16px_rgba(0,0,0,0.15)]";

/** Infinite, forward-looping card carousel with dots and swipe support. */
export function CardCarousel() {
  const [{ index, animate }, setPosition] = useState({ index: 0, animate: false });
  const busy = useRef(false);
  const touchStartX = useRef<number | null>(null);

  const isMobile = useMediaQuery("(max-width: 640px)");
  const isTablet = useMediaQuery("(max-width: 992px)");
  const perPage = isMobile ? 1 : isTablet ? 2 : 3;
  const dotCount = Math.ceil(REAL_COUNT / perPage);
  const activeDot = Math.floor((index % REAL_COUNT) / perPage);

  // Failsafe: a transition that never fires `transitionend` must not lock the carousel.
  useEffect(() => {
    if (!animate) return;
    const timer = setTimeout(() => (busy.current = false), 600);
    return () => clearTimeout(timer);
  }, [animate, index]);

  const next = useCallback(() => {
    if (busy.current) return;
    busy.current = true;
    setPosition((p) => ({ index: p.index + 1, animate: true }));
  }, []);

  const prev = useCallback(() => {
    if (busy.current) return;
    busy.current = true;
    if (index <= 0) {
      // Jump (without animation) to the cloned set, then slide back one step.
      setPosition({ index: REAL_COUNT, animate: false });
      requestAnimationFrame(() =>
        requestAnimationFrame(() => setPosition({ index: REAL_COUNT - 1, animate: true })),
      );
    } else {
      setPosition((p) => ({ index: p.index - 1, animate: true }));
    }
  }, [index]);

  const goToDot = (dot: number) => {
    const target = dot * perPage;
    if (busy.current || target === index) return;
    busy.current = true;
    setPosition({ index: target, animate: true });
  };

  const onTransitionEnd = () => {
    busy.current = false;
    if (index >= REAL_COUNT) setPosition({ index: index % REAL_COUNT, animate: false });
  };

  const onTouchStart = (event: TouchEvent) => {
    if (!busy.current) touchStartX.current = event.touches[0].clientX;
  };

  const onTouchMove = (event: TouchEvent) => {
    if (touchStartX.current === null || busy.current) return;
    const diff = event.touches[0].clientX - touchStartX.current;
    if (Math.abs(diff) > SWIPE_THRESHOLD_PX) {
      touchStartX.current = null;
      if (diff < 0) next();
      else prev();
    }
  };

  return (
    <section className="relative right-1/2 left-1/2 -mr-[50vw] -ml-[50vw] w-screen border-t border-black/8 bg-[#f2f4f6] py-[60px] max-[769px]:mb-[60px] max-[769px]:pt-[50px] max-[501px]:mb-0!">
      <div className="mx-auto mb-[45px] max-w-[850px] px-6 text-center">
        <h2 className="mb-3 text-[2.5rem] font-light tracking-[-0.3px] text-ink">
          Choose the Card you carry
        </h2>
        <p className="mx-auto text-[clamp(0.95rem,2vw,1.05rem)] leading-[1.6] font-light text-[#555]">
          Your Sterling membership is defined by its privileges. Your card is defined by you. Choose
          from a selection of distinctive materials and finishes.
        </p>
      </div>

      <div className="relative mx-auto flex max-w-[1340px] items-center px-[45px] max-[641px]:px-[35px]">
        <button
          type="button"
          aria-label="Previous Cards"
          onClick={prev}
          className={cn(navButton, "left-[2px] max-[641px]:-left-[5px]")}
        >
          <ArrowLeftSmallIcon />
        </button>

        <div
          className="[margin:-15px_-5px] w-full overflow-hidden px-[5px] py-[15px]"
          onTouchStart={onTouchStart}
          onTouchMove={onTouchMove}
          onTouchEnd={() => (touchStartX.current = null)}
        >
          <div
            onTransitionEnd={(event) => event.target === event.currentTarget && onTransitionEnd()}
            style={
              {
                "--idx": index,
                transform: `translateX(calc(var(--idx) * -1 * ((100% - (var(--per-page) - 1) * ${GAP_PX}px) / var(--per-page) + ${GAP_PX}px)))`,
                transition: animate ? "transform 0.4s cubic-bezier(0.25, 1, 0.5, 1)" : "none",
              } as React.CSSProperties
            }
            className="flex gap-6 will-change-transform [--per-page:3] max-[993px]:[--per-page:2] max-[641px]:[--per-page:1]"
          >
            {trackItems.map((card, i) => {
              const isClone = i >= REAL_COUNT;
              return (
                <div
                  key={`${card.name}-${i}`}
                  aria-hidden={isClone || undefined}
                  className="group box-border flex flex-[0_0_calc((100%-(var(--per-page)-1)*24px)/var(--per-page))] flex-col overflow-hidden rounded-xl border border-black/8 bg-white shadow-[0_4px_15px_rgba(0,0,0,0.04)] transition-[transform,box-shadow] duration-300 hover:-translate-y-1.5 hover:shadow-[0_12px_30px_rgba(0,0,0,0.12)]"
                >
                  <div
                    className={cn("relative aspect-[1.58/1] w-full overflow-hidden", card.backdrop)}
                  >
                    <Image
                      src={card.image.src}
                      alt={isClone ? "" : card.image.alt}
                      fill
                      sizes="(max-width: 640px) 100vw, (max-width: 992px) 50vw, 420px"
                      className="object-contain transition-transform duration-300 group-hover:scale-[1.04]"
                    />
                  </div>
                  <div className="flex grow items-center border-t border-black/4 bg-white px-6 pt-[22px] pb-[26px]">
                    <Link
                      href="#login"
                      tabIndex={isClone ? -1 : undefined}
                      className="inline-block text-[1.05rem] font-bold text-[#006fcf] transition-colors duration-200 hover:text-[#004b93] hover:underline"
                    >
                      {card.name}
                    </Link>
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        <button
          type="button"
          aria-label="Next Cards"
          onClick={next}
          className={cn(navButton, "right-[13px] max-[641px]:-right-[5px]")}
        >
          <ArrowRightSmallIcon />
        </button>
      </div>

      <div className="mt-8 flex items-center justify-center gap-[10px]">
        {Array.from({ length: dotCount }, (_, dot) => (
          <button
            key={dot}
            type="button"
            aria-label={`Go to slide group ${dot + 1}`}
            onClick={() => goToDot(dot)}
            className={cn(
              "size-[10px] cursor-pointer rounded-full p-0 transition-all duration-300",
              dot === activeDot ? "scale-125 bg-[#006fcf]" : "bg-[#9aa4b2]",
            )}
          />
        ))}
      </div>
    </section>
  );
}
