"use client";

import { useState, useMemo, useRef } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import { EffectCoverflow } from "swiper/modules";

import "swiper/css";
import "swiper/css/effect-coverflow";

import Image from "next/image";
import { withCDN, optimizedImage } from "@/src/lib/utils";
import { slugFallback } from "@/src/lib/programSlugFallback";
import LanguageAwareLink from "@/src/lib/utils/LanguageAwareLink";
import { detailHref } from "@/src/lib/utils/detailHref";
import type { Swiper as SwiperType } from "swiper";

export interface ProgramSlideInput {
  programHeading?: string;
  programTitle?: string;
  programImage?: string;
  programLogo?: string;
  programAge?: string;
  programSlug?: string;
  program_id?: string;
}

interface AboutSliderProps {
  programs?: ProgramSlideInput[];
  // The section's "Years Old Text", shown under every slide's age range.
  yearsOldText?: string;
}

const defaultSlides = [
  {
    slug: "ALGO_BUDDY",
    img: "https://yefranchisees.b-cdn.net/frontend/About/models-scroll.png",
    title: "Fan Moving Robot",
    logoImg: withCDN("/program-logo/logo_algo_buddy.svg"),
    age: "4-6",
    heading:
      "Program for developing Confidence in problem-solving and creative thinking",
  },
  {
    slug: "GALILEO_TECHNIC",
    img: "https://yefranchisees.b-cdn.net/frontend/About/spinning%20top%20bouncer.png",
    title: "Spinning Top Bouncer",
    logoImg: withCDN("/program-logo/logo_galileo_technic.svg"),
    age: "7-10",
    heading:
      "Program for developing Confidence in problem-solving and creative thinking",
  },
  {
    slug: "ALGOPLAY",
    img: "https://yefranchisees.b-cdn.net/frontend/About/Basketball.png",
    title: "Basketball",
    logoImg: withCDN("/program-logo/algo_play.svg"),
    age: "6-10",
    heading:
      "Program for developing Confidence in problem-solving and creative thinking",
  },
  {
    slug: "SMARTIVO",
    img: "https://yefranchisees.b-cdn.net/frontend/About/Sketching%20Smartivo_7%201.png",
    title: "Sketching Smartivo",
    logoImg: withCDN("/program-logo/logo_smartivo.svg"),
    age: "4-6",
    heading:
      "Program for developing Confidence in problem-solving and creative thinking",
  },
  {
    slug: "ALGOC",
    img: "https://yefranchisees.b-cdn.net/frontend/About/Card%20shuffler.png",
    title: "Card shuffler",
    logoImg: withCDN("/program-logo/logo_algo_c.svg"),
    age: "13-18",
    heading:
      "Program for developing Confidence in problem-solving and creative thinking",
  },
];

const normalizeSlug = (s?: string) =>
  s ? s.toString().toUpperCase().replace(/[^A-Z0-9]/g, "") : "";

const defaultBySlug: Record<string, (typeof defaultSlides)[number]> = {};

defaultSlides.forEach((d) => {
  if (d.slug) {
    defaultBySlug[normalizeSlug(d.slug)] = d;
  }
});

export default function AboutSlider({
  programs,
  yearsOldText,
}: AboutSliderProps) {
  const yearsOldLabel = yearsOldText?.trim() || "years old program";
  const [currentIndex, setCurrentIndex] = useState(0);

  const [thumbsSwiper, setThumbsSwiper] =
    useState<SwiperType | null>(null);

  const [mobileSwiper, setMobileSwiper] =
    useState<SwiperType | null>(null);

  const [isAnimating, setIsAnimating] = useState(false);

  /*
   * TABLET + DESKTOP SWIPE
   *
   * Pointer events allow:
   * - Touch swipe on tablet
   * - Mouse drag on desktop
   */
  const swipeStartRef = useRef<{
    x: number;
    y: number;
    pointerId: number;
  } | null>(null);

  const slides = useMemo(() => {
    const apiPrograms = (
      Array.isArray(programs) ? programs : []
    ).filter(
      (p) =>
        p &&
        (
          p.program_id ||
          p.programSlug ||
          p.programImage ||
          (p.programTitle &&
            p.programTitle.toString().trim()) ||
          (p.programHeading &&
            p.programHeading.toString().trim())
        )
    );

    if (apiPrograms.length === 0) {
      return defaultSlides.map((s) => ({
        ...s,
        programId: "",
        programSlug: "",
      }));
    }

    return apiPrograms.map((apiProgram, index) => {
      const fallback =
        defaultSlides[index % defaultSlides.length];

      const dSlug =
        defaultBySlug[
          normalizeSlug(apiProgram.programSlug)
        ];

      const bySlug =
        slugFallback(apiProgram.programSlug);

      return {
        img:
          apiProgram.programImage ||
          dSlug?.img ||
          bySlug?.image ||
          fallback.img,

        title:
          apiProgram.programTitle ||
          dSlug?.title ||
          "",

        logoImg:
          apiProgram.programLogo ||
          dSlug?.logoImg ||
          bySlug?.logoImage ||
          "",

        age:
          apiProgram.programAge ||
          dSlug?.age ||
          "",

        heading:
          apiProgram.programHeading ||
          "",

        programId:
          apiProgram.program_id || "",

        programSlug:
          apiProgram.programSlug || "",
      };
    });
  }, [programs]);

  // Switching language swaps the list while the slider stays mounted, and the
  // lists differ in length (French About has 2 programs, English 8). Reading
  // past the end crashed the page on `slide.img`, so everything - render and
  // the arrows alike - works from this index, never the stored one.
  const activeIndex = currentIndex < slides.length ? currentIndex : 0;

  const slide = slides[activeIndex];

  const prevIndex =
    activeIndex === 0
      ? slides.length - 1
      : activeIndex - 1;

  const nextIndex =
    activeIndex === slides.length - 1
      ? 0
      : activeIndex + 1;

  const prevSlide = slides[prevIndex];
  const nextSlide = slides[nextIndex];

  /* PREVIOUS SLIDE */
  const prev = () => {
    if (isAnimating) return;

    /* MOBILE */
    if (window.innerWidth < 768) {
      mobileSwiper?.slidePrev();
      return;
    }

    /*TABLET + DESKTOP */
    const newIndex = prevIndex;

    setCurrentIndex(newIndex);

    thumbsSwiper?.slideTo(newIndex);
  };

  /* NEXT SLIDE */
  const next = () => {
    if (isAnimating) return;

    /* MOBILE */
    if (window.innerWidth < 768) {
      mobileSwiper?.slideNext();
      return;
    }

    /* TABLET + DESKTOP */
    const newIndex = nextIndex;

    setCurrentIndex(newIndex);

    thumbsSwiper?.slideTo(newIndex);
  };

  /* MOBILE SWIPE */
  const handleMobileSwipe = (
    direction: "next" | "prev"
  ) => {
    if (
      window.innerWidth >= 768 ||
      isAnimating
    ) {
      return;
    }

    if (direction === "next") {
      mobileSwiper?.slideNext();
    } else {
      mobileSwiper?.slidePrev();
    }
  };

  /*
   * ============================================================
   * TABLET + DESKTOP POINTER SWIPE
   * ============================================================
   */

  const handleTabletDesktopPointerDown = (
    e: React.PointerEvent<HTMLDivElement>
  ) => {
    if (window.innerWidth < 768) return;

    /*
     * Don't start a swipe when clicking:
     * - buttons
     * - links
     *
     * This prevents arrows and program links
     * from accidentally triggering a slide.
     */
    const target = e.target as HTMLElement;

    if (target.closest("button, a")) {
      return;
    }

    swipeStartRef.current = {
      x: e.clientX,
      y: e.clientY,
      pointerId: e.pointerId,
    };

    /*
     * Keep receiving pointer events even if
     * the pointer moves outside the element.
     */
    e.currentTarget.setPointerCapture(
      e.pointerId
    );
  };

  const handleTabletDesktopPointerUp = (
    e: React.PointerEvent<HTMLDivElement>
  ) => {
    if (window.innerWidth < 768) return;

    const start = swipeStartRef.current;

    if (!start) return;

    const diffX =
      start.x - e.clientX;

    const diffY =
      start.y - e.clientY;

    swipeStartRef.current = null;

    /*Release pointer capture.*/
    if (
      e.currentTarget.hasPointerCapture(
        e.pointerId
      )
    ) {
      e.currentTarget.releasePointerCapture(
        e.pointerId
      );
    }

    /*
     * This allows normal page scrolling.
     */
    if (
      Math.abs(diffY) >
      Math.abs(diffX)
    ) {
      return;
    }

    /*
     * Minimum swipe / drag distance.
     */
    if (Math.abs(diffX) < 50) {
      return;
    }

    /*
     * Swipe LEFT
     * → NEXT
     */
    if (diffX > 0) {
      next();
    }

    /*
     * Swipe RIGHT
     * → PREVIOUS
     */
    else {
      prev();
    }
  };

  const handleTabletDesktopPointerCancel = (
    e: React.PointerEvent<HTMLDivElement>
  ) => {
    swipeStartRef.current = null;

    if (
      e.currentTarget.hasPointerCapture(
        e.pointerId
      )
    ) {
      e.currentTarget.releasePointerCapture(
        e.pointerId
      );
    }
  };

  return (
    <div className="w-full lg:pl-12 relative pl-0 a-sliders mt-[20px]">

      {/* ======================================================
          MAIN CONTENT
          ====================================================== */}

      <div className="grid grid-cols-1 md:grid-cols-12 gap-4 md:gap-10 items-center">

        {/* ====================================================
            DESKTOP + TABLET IMAGE
            ==================================================== */}

        <div
          className="md:col-span-5 xl:col-span-5 relative h-[300px] md:h-[360px] xl:h-[520px] overflow-visible hidden md:block md:cursor-grab md:active:cursor-grabbing md:select-none"

          /*
           * KEEP IMAGE SWIPE
           *
           * This means the image continues to work exactly
           * like before.
           */
          onPointerDown={
            handleTabletDesktopPointerDown
          }
          onPointerUp={
            handleTabletDesktopPointerUp
          }
          onPointerCancel={
            handleTabletDesktopPointerCancel
          }

          style={{
            touchAction: "pan-y",
          }}
        >
          {/* MAIN IMAGE */}
          <div
            className={`absolute inset-0 ${
              isAnimating
                ? "opacity-0"
                : "opacity-100"
            }`}
          >
            <Image
              src={slide.img}
              alt={slide.title}
              fill
              sizes="(max-width: 768px) 100vw, 50vw"
              className={`object-contain max-md:transition-all max-md:duration-[800ms] max-md:ease-out about-highlight-img ${
                isAnimating
                  ? "max-md:scale-[.05] max-md:opacity-0"
                  : "scale-100 opacity-100"
              }`}
            />
          </div>

          {/* DESKTOP TITLE */}
          <div className="absolute inset-0 flex flex-col justify-end p-4">
            {slide.title && (
              <h3 className="hidden md:block text-[#0097dc] text-[15px] md:text-[14px] lg:text-[15px] uppercase py-[10px] px-[30px] rounded-full bg-white shadow-[6px_6px_14px_#00000040] w-fit mb-[0px] xl:mb-[10px] md:mb-[0px]">
                {slide.title}
              </h3>
            )}
          </div>
        </div>

        {/* ====================================================
            MOBILE IMAGE SLIDER
            ==================================================== */}

        <div className="md:hidden w-full overflow-hidden">
          <Swiper
            modules={[EffectCoverflow]}
            effect="coverflow"
            centeredSlides={true}
            slidesPerView={1.8}
            spaceBetween={0}
            initialSlide={activeIndex}
            loop={true}
            speed={600}
            onSwiper={setMobileSwiper}
            coverflowEffect={{
              rotate: 0,
              stretch: 0,
              depth: 0,
              modifier: 1,
              scale: 0.72,
              slideShadows: false,
            }}
            onSlideChange={(swiper) => {
              const realIndex =
                swiper.realIndex;

              setCurrentIndex(realIndex);

              if (thumbsSwiper) {
                thumbsSwiper.slideTo(
                  realIndex
                );
              }
            }}
            className="mobile-image-slider"
          >
            {slides.map((item, i) => (
              <SwiperSlide
                key={`mobile-image-${item.title}-${i}`}
              >
                <div
                  className={`relative w-full h-[210px] transition-all duration-500 ${
                    activeIndex === i
                      ? "scale-100 opacity-100 mobile-main-img"
                      : "scale-[0.72] opacity-60"
                  }`}
                >
                  <Image
                    src={item.img}
                    alt={
                      item.title ||
                      `Slide ${i + 1}`
                    }
                    fill
                    sizes="80vw"
                    className="object-contain"
                  />
                </div>
              </SwiperSlide>
            ))}
          </Swiper>
        </div>

        {/* ====================================================
            CONTENT
            ==================================================== */}

        <div
          className="md:col-span-7 xl:col-span-7 relative md:cursor-grab md:active:cursor-grabbing md:select-none"

          /*
           * MOBILE TOUCH
           * TABLET + DESKTOP
           */

          onPointerDown={(e) => {
            if (window.innerWidth < 768) {
              return;
            }

            handleTabletDesktopPointerDown(e);
          }}

          onPointerUp={(e) => {
            if (window.innerWidth < 768) {
              return;
            }

            handleTabletDesktopPointerUp(e);
          }}

          onPointerCancel={(e) => {
            if (window.innerWidth < 768) {
              return;
            }

            handleTabletDesktopPointerCancel(e);
          }}

          /*
           * EXISTING MOBILE TOUCH HANDLERS
           */
          onTouchStart={(e) => {
            if (window.innerWidth >= 768) {
              return;
            }

            (
              e.currentTarget as HTMLElement
            ).dataset.touchStartX =
              String(
                e.touches[0].clientX
              );
          }}

          onTouchEnd={(e) => {
            if (window.innerWidth >= 768) {
              return;
            }

            const startX = Number(
              (
                e.currentTarget as HTMLElement
              ).dataset.touchStartX
            );

            const endX =
              e.changedTouches[0].clientX;

            const diff =
              startX - endX;

            if (Math.abs(diff) < 50) {
              return;
            }

            if (diff > 0) {
              handleMobileSwipe("next");
            } else {
              handleMobileSwipe("prev");
            }
          }}

          style={{
            touchAction: "pan-y",
          }}
        >
          <div className="w-full text-center flex flex-col items-center md:items-start justify-center gap-0 px-4 md:px-0">

            {/* ==================================================
                LOGO + AGE
                ================================================== */}

            {(slide.logoImg || slide.age) && (
              <div className="flex items-center gap-2 sm:gap-5 mb-5 w-[95%] max-[767px]:justify-center">

                {/* LOGO */}
                {slide.logoImg &&
                  (() => {
                    const boxClass =
                      "w-[81px] h-[53px] md:w-[160px] md:h-[106px] lg:w-[180px] lg:h-[120px] bg-white rounded-[19px] md:rounded-[32px] lg:rounded-[46px] flex items-center justify-center";

                    const logo = (
                      <Image
                        src={
                          slide.logoImg
                        }
                        alt={
                          slide.title ||
                          "program logo"
                        }
                        width={70}
                        height={70}
                        className="m-auto w-[81px] h-[53px] md:h-[106px] md:w-[164px] lg:w-[174px] lg:h-[120px] lg:w-[180px] lg:h-[120px] object-cover"
                      />
                    );

                    if (
                      !slide.programId
                    ) {
                      return (
                        <div
                          className={
                            boxClass
                          }
                        >
                          {logo}
                        </div>
                      );
                    }

                    return (
                      <LanguageAwareLink
                        href={detailHref(
                          "/programs",
                          slide.programId,
                          slide.programSlug
                        )}
                        aria-label={
                          slide.title
                            ? `Open the ${slide.title} program page`
                            : "Open the program page"
                        }
                        className={
                          boxClass
                        }
                      >
                        {logo}
                      </LanguageAwareLink>
                    );
                  })()}

                {/* AGE */}
                {slide.age && (
                  <p className="relative z-10 text-left text-[40px] xl:text-[50px] xl:leading-[50px] font-bold text-white max-[767px]:text-[32px] max-[767px]:text-center uppercase">
                    {slide.age}

                    <span className="block relative z-10 text-center md:text-left lg:text-center text-[20px] font-light text-white max-[767px]:text-[10px] max-[767px]:leading-[10px]">
                      {yearsOldLabel}
                    </span>
                  </p>
                )}
              </div>
            )}

            {/* ==================================================
                HEADING
                ================================================== */}

            <div className="p-3 relative mb-6 lg:mb-24 xl:mb-32 xl:w-[590px] md:min-h-[120px] lg:min-h-[100px] about-content-right">
              <h3 className="relative z-10 text-left text-[20px] xl:text-[25px] text-white flex items-start uppercase max-[767px]:text-[18px] max-[767px]:text-center">
                {slide.heading}
              </h3>
            </div>

            {/* ==================================================
                ARROWS
                ================================================== */}

            <div className="flex items-center justify-between w-full md:px-3 md:max-w-full max-[767px]:justify-center max-[767px]:gap-4 max-[767px]:mt-[-40px] about-slider-arrow">

              {/* PREVIOUS */}
              <button
                onClick={prev}
                aria-label="Previous slide"
                className="rounded-full flex items-center justify-center scroll-btn z-9"
              >
                <Image
                  src={withCDN(
                    "/arrow%20up.png"
                  )}
                  alt="Previous"
                  width={32}
                  height={32}
                  className="object-contain cursor-pointer rotate-[268deg]"
                />
              </button>

              {/* NEXT */}
              <button
                onClick={next}
                aria-label="Next slide"
                className="rounded-full flex items-center justify-center scroll-btn z-9"
              >
                <Image
                  src={withCDN(
                    "/arrow%20up.png"
                  )}
                  alt="Next"
                  width={32}
                  height={32}
                  className="object-contain cursor-pointer rotate-[90deg]"
                />
              </button>

            </div>
          </div>
        </div>
      </div>

      {/* ======================================================
          THUMBNAIL SLIDER
          ====================================================== */}

      <div className="thumbnail-slider w-1/2 ml-auto mr-auto md:mr-11 -mt-38 hidden md:block">
        <Swiper
          onSwiper={setThumbsSwiper}
          spaceBetween={10}
          breakpoints={{
            768: {
              slidesPerView: 3,
            },
            1024: {
              slidesPerView: Math.min(
                4.6,
                Math.max(1, slides.length)
              ),
            },
          }}
          className="mt-3 md:mt-0 lg: mt-3 hidden md:block thumbs-swiper"
        >
          {slides.map((slide, i) => (
            <SwiperSlide
              key={`thumb-${slide.title}-${i}`}
            >
              <div
                onClick={() => {
                  if (!isAnimating) {
                    setCurrentIndex(i);
                  }
                }}
                className={`thumb-item relative md:h-[120px] h-[60px] cursor-pointer flex flex-col items-center transition-opacity duration-150 ${
                  activeIndex === i
                    ? "opacity-100 border-b-2 border-[#0097DC] pb-2"
                    : "opacity-90"
                }`}
              >
                <img
                  src={optimizedImage(slide.img, 1080)}
                  alt={
                    slide.title ||
                    `thumb-${i}`
                  }
                  className="w-full h-full object-contain rounded-[20px]"
                />
              </div>
            </SwiperSlide>
          ))}
        </Swiper>
      </div>
    </div>
  );
}
