"use client";

import { useEffect } from "react";

/**
 * Wires up `/affiliate`'s `.review_box` (raw `.review_box_1` cards) with the
 * real Slick config from `affiliate.php`'s script block — `arrows:true,
 * dots:false, slidesToShow:3`, `breakpoint:991 → slidesToShow:2`,
 * `breakpoint:480 → arrows:false, dots:true, slidesToShow:1` — reproduced
 * with CSS scroll-snap instead of porting Slick itself, same approach as
 * `WhyChooseSlider`. `become-partner.css`'s own `.slick-next`/`.slick-prev`/
 * `.slick-dots` rules (copied verbatim from the live template) style these
 * directly, so the injected arrow/dot elements reuse Slick's real class
 * names rather than inventing new ones.
 *
 * Slick's real DOM nests the scrollable track (`.slick-list`, `overflow:
 * hidden`) *inside* the position:relative slider root, with the arrows as
 * separate siblings of the list — not children of the thing that scrolls.
 * Putting the arrows inside the scrollable element itself would clip them
 * at the edges (the CSS positions them at `left:-35px`/`right:-35px`,
 * outside the track). This reproduces that two-level structure: `.review_box`
 * stays the (position:relative, via the real `.slick-slider` class) outer
 * root, with a new inner `.review_box_track` wrapping the actual cards as
 * the thing that scrolls.
 *
 * DOM creation (track/arrows/dots) is idempotent — guarded by checking for
 * an existing `.review_box_track`, not a one-shot `dataset` flag — but
 * listeners are always freshly attached on every effect run. A one-shot
 * "already set up, skip entirely" guard breaks clicks after React Strict
 * Mode's dev-only mount→cleanup→mount cycle (first mount attaches
 * listeners, Strict Mode's cleanup removes them, second mount sees the DOM
 * already built and skips re-attaching) — this exact bug was already found
 * and fixed once in `WhyChooseSlider`; reproduced here too before it shipped.
 */
export function AffiliateReviewsCarousel() {
  useEffect(() => {
    const boxes = document.querySelectorAll<HTMLElement>(".affiliate-review .review_box");
    const cleanups: Array<() => void> = [];

    boxes.forEach((box) => {
      box.classList.add("slick-slider", "slick-initialized");

      let track = box.querySelector<HTMLElement>(":scope > .review_box_track");
      if (!track) {
        const cards = Array.from(box.querySelectorAll<HTMLElement>(":scope > .review_box_1"));
        if (cards.length <= 1) return;

        track = document.createElement("div");
        track.className = "review_box_track";
        box.insertBefore(track, cards[0]);
        cards.forEach((card) => track!.appendChild(card));

        const prevBtn = document.createElement("button");
        const nextBtn = document.createElement("button");
        prevBtn.type = "button";
        nextBtn.type = "button";
        prevBtn.className = "slick-prev";
        nextBtn.className = "slick-next";
        prevBtn.setAttribute("aria-label", "Previous review");
        nextBtn.setAttribute("aria-label", "Next review");
        box.appendChild(prevBtn);
        box.appendChild(nextBtn);

        const dotsRow = document.createElement("ul");
        dotsRow.className = "slick-dots";
        box.appendChild(dotsRow);
        cards.forEach((_, i) => {
          const li = document.createElement("li");
          if (i === 0) li.classList.add("slick-active");
          const dotBtn = document.createElement("button");
          dotBtn.type = "button";
          dotBtn.setAttribute("aria-label", `Go to review ${i + 1}`);
          li.appendChild(dotBtn);
          dotsRow.appendChild(li);
        });
      }

      const resolvedTrack = track;
      const cards = Array.from(resolvedTrack.querySelectorAll<HTMLElement>(":scope > .review_box_1"));
      const prevBtn = box.querySelector<HTMLButtonElement>(":scope > .slick-prev");
      const nextBtn = box.querySelector<HTMLButtonElement>(":scope > .slick-next");
      const dotsRow = box.querySelector<HTMLElement>(":scope > .slick-dots");
      if (!prevBtn || !nextBtn || !dotsRow || cards.length <= 1) return;

      const getStep = () => (cards.length > 1 ? cards[1].offsetLeft - cards[0].offsetLeft : resolvedTrack.clientWidth);

      const onPrev = () => resolvedTrack.scrollBy({ left: -getStep(), behavior: "smooth" });
      const onNext = () => resolvedTrack.scrollBy({ left: getStep(), behavior: "smooth" });
      prevBtn.addEventListener("click", onPrev);
      nextBtn.addEventListener("click", onNext);

      const dotHandlers = Array.from(dotsRow.querySelectorAll<HTMLButtonElement>("button")).map((dot, i) => {
        const handler = () => resolvedTrack.scrollTo({ left: i * getStep(), behavior: "smooth" });
        dot.addEventListener("click", handler);
        return { dot, handler };
      });

      let scrollTimeout: ReturnType<typeof setTimeout>;
      const onScroll = () => {
        clearTimeout(scrollTimeout);
        scrollTimeout = setTimeout(() => {
          const step = getStep();
          const index = step > 0 ? Math.round(resolvedTrack.scrollLeft / step) : 0;
          dotsRow.querySelectorAll("li").forEach((li, i) => li.classList.toggle("slick-active", i === index));
        }, 100);
      };
      resolvedTrack.addEventListener("scroll", onScroll, { passive: true });

      cleanups.push(() => {
        clearTimeout(scrollTimeout);
        prevBtn.removeEventListener("click", onPrev);
        nextBtn.removeEventListener("click", onNext);
        dotHandlers.forEach(({ dot, handler }) => dot.removeEventListener("click", handler));
        resolvedTrack.removeEventListener("scroll", onScroll);
      });
    });

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

  return null;
}
