"use client";

import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
import type { GoogleReview } from "@/lib/google-reviews";
import { ReviewCard } from "./ReviewCard";

const INTERVAL_MS = 5000;
const GAP_PX = 16;
const SLIDE_EASE = "cubic-bezier(0.25, 0.46, 0.45, 0.94)";

type Props = {
  reviews: GoogleReview[];
};

type CarouselMetrics = {
  itemW: number;
  step: number;
  maxVisible: number;
};

function getMaxVisible(width: number): number {
  if (width >= 1024) return 3;
  if (width >= 640) return 2;
  return 1;
}

function positionCount(len: number, maxVisible: number) {
  return Math.max(0, len - maxVisible + 1);
}

export function ReviewsCarousel({ reviews }: Props) {
  const viewportRef = useRef<HTMLDivElement>(null);
  const [startIndex, setStartIndex] = useState(0);
  const [paused, setPaused] = useState(false);
  const [metrics, setMetrics] = useState<CarouselMetrics>({
    itemW: 0,
    step: 0,
    maxVisible: 1,
  });

  const len = reviews.length;
  const { maxVisible, itemW, step } = metrics;
  const positions = positionCount(len, maxVisible);

  useLayoutEffect(() => {
    const el = viewportRef.current;
    if (!el) return;

    function measure() {
      const node = viewportRef.current;
      if (!node) return;
      const w = node.clientWidth;
      if (w <= 0) return;
      const visible = getMaxVisible(w);
      const nextItemW = (w - (visible - 1) * GAP_PX) / visible;
      const nextStep = nextItemW + GAP_PX;
      setMetrics((m) =>
        m.itemW === nextItemW &&
        m.step === nextStep &&
        m.maxVisible === visible
          ? m
          : { itemW: nextItemW, step: nextStep, maxVisible: visible }
      );
    }

    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(el);
    return () => ro.disconnect();
  }, []);

  const advance = useCallback(() => {
    if (len <= maxVisible || positions <= 1) return;
    setStartIndex((i) => (i + 1) % positions);
  }, [len, maxVisible, positions]);

  useEffect(() => {
    if (len <= maxVisible || paused || positions <= 1) return undefined;
    const t = window.setInterval(advance, INTERVAL_MS);
    return () => window.clearInterval(t);
  }, [len, maxVisible, paused, positions, advance]);

  useEffect(() => {
    if (startIndex >= positions) setStartIndex(0);
  }, [startIndex, positions]);

  function goToPosition(i: number) {
    if (i < 0 || i >= positions || i === startIndex) return;
    setStartIndex(i);
  }

  if (len <= 3) {
    const gridClass =
      len === 1
        ? "mx-auto grid max-w-md grid-cols-1 gap-4"
        : len === 2
          ? "mx-auto grid max-w-2xl grid-cols-1 gap-4 sm:grid-cols-2"
          : "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3";

    return (
      <div className={gridClass}>
        {reviews.map((review) => (
          <ReviewCard key={review.id} review={review} />
        ))}
      </div>
    );
  }

  const translateX = step > 0 ? -startIndex * step : 0;
  const fallbackWidth =
    maxVisible === 1
      ? "100%"
      : maxVisible === 2
        ? "calc((100% - 16px) / 2)"
        : "calc((100% - 32px) / 3)";

  return (
    <div
      className="relative"
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
    >
      <div ref={viewportRef} className="overflow-hidden">
        <div
          className="flex flex-row flex-nowrap items-stretch gap-4 will-change-transform"
          style={{
            transform: `translateX(${translateX}px)`,
            transition: `transform 650ms ${SLIDE_EASE}`,
          }}
        >
          {reviews.map((review) => (
            <div
              key={review.id}
              className="flex shrink-0 self-stretch"
              style={
                itemW > 0
                  ? { width: itemW, minWidth: itemW }
                  : { width: fallbackWidth, minWidth: fallbackWidth }
              }
            >
              <ReviewCard review={review} />
            </div>
          ))}
        </div>
      </div>

      {positions > 1 ? (
        <div className="mt-6 flex flex-wrap justify-center gap-1.5">
          {Array.from({ length: positions }).map((_, i) => (
            <button
              key={`dot-${i}`}
              type="button"
              aria-label={`Avis ${i + 1} sur ${positions}`}
              aria-current={i === startIndex}
              onClick={() => goToPosition(i)}
              className={`h-2 rounded-full transition-all duration-500 ease-out ${
                i === startIndex
                  ? "w-8 bg-gaufre"
                  : "w-2 bg-chocolat/30 hover:bg-chocolat/50"
              }`}
            />
          ))}
        </div>
      ) : null}
    </div>
  );
}
