"use client";

import { useEffect } from "react";

interface CarouselTarget {
  /** Selector for the scrollable row itself. */
  rowSelector: string;
  /** Class names for the inserted wrapper/arrow elements — kept distinct
   *  per target so each section's CSS (`app/css/tool-pages.css`) can style
   *  its own arrows without the two bleeding into each other. */
  wrapperClass: string;
  arrowClass: string;
  prevClass: string;
  nextClass: string;
  /** Selector for a single card, used to measure the scroll-by amount. */
  cardSelector: string;
  /** Arrow icon markup. Defaults to a plain chevron; `/tools` overrides this
   *  with the real `CaretLeft.svg`/`CaretRight.svg` icons Slick itself uses
   *  for `.new_testimonials` (see `templates/GAH/scss/common/_common.scss`),
   *  since that section's arrows are plain icon buttons, not the circular
   *  white button `.ai-essay-reviews` uses. */
  prevIcon?: string;
  nextIcon?: string;
}

const DEFAULT_PREV_ICON = `<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="pointer-events:none"><path d="m15 18-6-6 6-6"/></svg>`;
const DEFAULT_NEXT_ICON = `<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="pointer-events:none"><path d="m9 18 6-6-6-6"/></svg>`;

const TARGETS: CarouselTarget[] = [
  {
    rowSelector: ".ai-essay-reviews .reviews-row",
    wrapperClass: "reviews-wrapper",
    arrowClass: "reviews-arrow",
    prevClass: "reviews-arrow-prev",
    nextClass: "reviews-arrow-next",
    cardSelector: ".box, :scope > div",
  },
  {
    // `/tools`' "Check Out the Reviews of Students..." section — same real
    // `.new_testimonials_slide`/`.test-testimonial` markup the live site
    // pages through with Slick (see `app/css/tool-pages.css`).
    rowSelector: ".new_testimonials_slide",
    wrapperClass: "new_testimonials_wrapper",
    arrowClass: "new_testimonials_arrow",
    prevClass: "new_testimonials_arrow-prev",
    nextClass: "new_testimonials_arrow-next",
    cardSelector: ".test-testimonial, :scope > div",
    prevIcon: `<img src="/images/CaretLeft.svg" alt="" width="40" height="40" style="pointer-events:none" />`,
    nextIcon: `<img src="/images/CaretRight.svg" alt="" width="40" height="40" style="pointer-events:none" />`,
  },
];

/**
 * Wires up left/right navigation chevrons for raw-CMS review/testimonial
 * rows (`.ai-essay-reviews .reviews-row`, `.new_testimonials_slide`) and
 * hides their native scrollbar line. The live site pages through this
 * markup with the Slick carousel JS plugin; this app doesn't load Slick, so
 * these become horizontally-scrollable rows with arrow buttons instead of a
 * true infinite-loop carousel.
 */
export function ReviewsCarousel() {
  useEffect(() => {
    const cleanups: Array<() => void> = [];

    TARGETS.forEach(({ rowSelector, wrapperClass, arrowClass, prevClass, nextClass, cardSelector, prevIcon, nextIcon }) => {
      const rows = document.querySelectorAll<HTMLElement>(rowSelector);

      rows.forEach((row) => {
        // Idempotent on the DOM shape, not a one-shot `dataset` flag: React's
        // dev-mode Strict Mode double-invokes this effect (mount → cleanup →
        // mount), and a `dataset.carouselReady` guard made the *second* mount
        // skip re-attaching listeners (since the wrapper/buttons from the
        // first mount were still there) right after the first mount's
        // cleanup had already removed its own — buttons rendered, but no
        // click handler survived either pass. Reusing the existing
        // wrapper/buttons when already wrapped, and always (re)attaching
        // this mount's own listeners, fixes that for both strict-mode dev
        // and plain single-mount production.
        let wrapper = row.parentElement;
        let prevBtn: HTMLButtonElement | null = null;
        let nextBtn: HTMLButtonElement | null = null;

        if (wrapper?.classList.contains(wrapperClass)) {
          prevBtn = wrapper.querySelector<HTMLButtonElement>(`.${prevClass}`);
          nextBtn = wrapper.querySelector<HTMLButtonElement>(`.${nextClass}`);
        } else {
          wrapper = document.createElement("div");
          wrapper.className = wrapperClass;
          row.parentElement?.insertBefore(wrapper, row);
          wrapper.appendChild(row);

          prevBtn = document.createElement("button");
          nextBtn = document.createElement("button");
          prevBtn.type = "button";
          nextBtn.type = "button";
          prevBtn.className = `${arrowClass} ${prevClass}`;
          nextBtn.className = `${arrowClass} ${nextClass}`;
          prevBtn.setAttribute("aria-label", "Previous review");
          nextBtn.setAttribute("aria-label", "Next review");

          prevBtn.innerHTML = prevIcon ?? DEFAULT_PREV_ICON;
          nextBtn.innerHTML = nextIcon ?? DEFAULT_NEXT_ICON;

          wrapper.appendChild(prevBtn);
          wrapper.appendChild(nextBtn);
        }

        if (!prevBtn || !nextBtn) return;
        const finalPrevBtn = prevBtn;
        const finalNextBtn = nextBtn;

        const scrollByCard = (dir: 1 | -1) => {
          const card = row.querySelector<HTMLElement>(cardSelector);
          const amount = (card?.offsetWidth ?? 340) + 16;
          row.scrollBy({ left: dir * amount, behavior: "smooth" });
        };

        const onPrev = (e: MouseEvent) => {
          e.preventDefault();
          e.stopPropagation();
          scrollByCard(-1);
        };

        const onNext = (e: MouseEvent) => {
          e.preventDefault();
          e.stopPropagation();
          scrollByCard(1);
        };

        finalPrevBtn.addEventListener("click", onPrev);
        finalNextBtn.addEventListener("click", onNext);

        cleanups.push(() => {
          finalPrevBtn.removeEventListener("click", onPrev);
          finalNextBtn.removeEventListener("click", onNext);
        });
      });
    });

    return () => cleanups.forEach((cleanup) => cleanup());
  }, []);

  return null;
}
