
"use client";

import { useState, useRef, useEffect } from "react";
import { useLanguage } from "@/src/lib/context/LanguageContext";
import { detailHref } from "@/src/lib/utils/detailHref";
import Image from "next/image";
import { withCDN, optimizedImage } from "@/src/lib/utils";
import { Swiper, SwiperSlide } from "swiper/react";
import type { Swiper as SwiperType } from "swiper";
import type { ProgramsPageSection } from "@/src/lib/services/programsPageService";
import WorkshopCardSkeleton from "../ui/skeletons/WorkshopCardSkeleton";
import LanguageAwareLink from "@/src/lib/utils/LanguageAwareLink";
import "swiper/css";

type ProgramCard = {
  id: string;
  slug: string;
  title: string;
  subtitle: string;
  description: string;
  ageRange: string;
  AiGradientStart?: string;
  AiGradientEnd?: string;
  createdFor: string;
  ageText: string;
  lessonDurationText: string;
  durationUnit: string;
  lessonDuration: string;
  lessonsTotal: string;
  ribbon: string;
  borderColor: string;
  iconSrc: string;
  imageSrc: string;
  parentProgramsId?: string | null;
  language?: string | null;
};

function extractBaseSlug(slug: string): string {
  return slug;
}


function renderSubtitleWithAIGradient(
  subtitle: string,
  gradientStart?: string,
  gradientEnd?: string
) {
  // Match AI abbreviations independently of letter casing.
  // Add translated abbreviations here if your translations use others.
  const aiPattern = /(\bAI\b|\bIA\b)/gi;

  return subtitle.split(aiPattern).map((word, index) => {
    const isAITag = /^(AI|IA)$/i.test(word);

    if (!isAITag) {
      return <span key={index}>{word}</span>;
    }

    return (
      <span
        key={index}
        className="inline-flex items-center justify-center text-white px-3 py-[1px] rounded-[10px] text-[20px] xl:text-[18px] xl:leading-[28px] leading-[30px] max-[330px]:text-[17px] max-[330px]:leading-[24px] max-[330px]:px-2"
        style={{
          background: `linear-gradient(265deg, ${
            gradientStart || "#4B134A"
          }, ${gradientEnd || "#993F98"})`,
        }}
      >
        {word}
      </span>
    );
  });
}


function getStaticAttributesBySlug(
  slug: string
): Partial<ProgramCard> | null {
  const baseSlug = extractBaseSlug(slug);

  const matchedProgram = FALLBACK_PROGRAMS.find(
    (prog) => extractBaseSlug(prog.slug) === baseSlug
  );

  if (matchedProgram) {
    return {
      ribbon: matchedProgram.ribbon,
      borderColor: matchedProgram.borderColor,
      iconSrc: matchedProgram.iconSrc,
      imageSrc: matchedProgram.imageSrc,
      AiGradientStart: matchedProgram.AiGradientStart,
      AiGradientEnd: matchedProgram.AiGradientEnd,
    };
  }

  return {
    ribbon: withCDN("/programs-page/bg%20%287%29%20%281%29.png"),
    borderColor: "#00AEEF",
    iconSrc: withCDN("/programs-page/AllPrograms/logo.svg"),
    imageSrc: withCDN("/programs-page/AllPrograms/allPrograms1.svg"),
    AiGradientStart: "#4B134A",
    AiGradientEnd: "#993F98",
  };
}

const FALLBACK_PROGRAMS: ProgramCard[] = [
  {
    id: "algo-buddy",
    slug: "ALGO_BUDDY",
    title: "ALGO BUDDY",
    subtitle: "LEARN BASIC PROGRAMMING",
    description:
      "where young children are introduced to the basics of programming through playful story-missions. Using colorful blocks and interactive apps, kids learn coding concepts at their own pace.",
    ageRange: "4-6",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "45",
    lessonsTotal: "20 lessons total",
    ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png"),
    borderColor: "#00AEEF",
    iconSrc: withCDN("/program-logo/logo_algo_buddy.svg"),
    imageSrc: withCDN("/programs-page/photo%20(8)%20(3).png"),
    AiGradientStart: "#0091d6",
    AiGradientEnd: "#61bae5",
  },
  {
    id: "bricks",
    slug: "BRICKS_CHALLENGE",
    title: "BRICKS CHALLENGE",
    subtitle: "WELCOME TO BRICKS CHALLENGE — A DYNAMIC PROGRAM",
    description:
      "Where kids learn science and engineering by building moving models. Through real-world themes like physics, energy, and motion, children discover how things work — all while having fun.",
    ageRange: "6–10",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "75",
    lessonsTotal: "36 lessons total",
    ribbon: withCDN("/Workshop/bg%20%284%29.png"),
    borderColor: "#8CC63F",
    iconSrc: withCDN("/program-logo/logo_bricks_chalenge.svg"),
    imageSrc: withCDN("/programs-page/AllPrograms/allPrograms1.svg"),
    AiGradientStart: "#95C11F",
    AiGradientEnd: "#226B20",
  },
  {
    id: "algo",
    slug: "ALGOPLAY",
    title: "ALGO PLAY",
    subtitle:
      "WELCOME TO AN IMMERSIVE, HANDS-ON ROBOTICS AND CODING ADVENTURE",
    description:
      "Using the unique Algo bricks system, kids build fun models and create graphical code sequences to bring them to life. It's engaging, educational, and designed for curious minds!",
    ageRange: "6–10",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "75",
    lessonsTotal: "36 lessons total",
    ribbon: withCDN("/programs-page/bg%20%287%29%20%281%29.png"),
    borderColor: "#92278F",
    iconSrc: withCDN("/program-logo/algo_play.svg"),
    imageSrc: withCDN("/programs-page/photo%20(4)%20(1).png"),
    AiGradientStart: "#4B134A",
    AiGradientEnd: "#993F98",
  },
  {
    id: "galileo",
    slug: "GALILEO_TECHNIC",
    title: "GALILEO TECHNICS",
    subtitle:
      "WELCOME TO GALILEO TECHNIC — AN ADVANCED STEM PROGRAM",
    description:
      "Older kids explore real mechanical principles like torque, motion, and energy using custom building kits. They create machines, solve challenges, and understand how technology works.",
    ageRange: "7–10",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "75",
    lessonsTotal: "36 lessons total",
    ribbon: withCDN("/programs-page/bg%20%284%29%20%281%29.png"),
    borderColor: "#ED1C24",
    iconSrc: withCDN("/program-logo/logo_galileo_technic.svg"),
    imageSrc: withCDN("/programs-page/photo%20(5)%20(1).png"),
    AiGradientStart: "#ED174C",
    AiGradientEnd: "#8B0025",
  },
  {
    id: "robo",
    slug: "ROBO_TOYS",
    title: "ROBO TOYS",
    subtitle:
      "WELCOME TO ROBO TOYS — A CREATIVE ROBOTICS COURSE",
    description:
      "In this course, kids build fun, interactive machines and bring them to life using simple code. Each class combines play, storytelling, and hands-on building to teach real STEM and logic skills.",
    ageRange: "9–12",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "75",
    lessonsTotal: "36 lessons total",
    ribbon: withCDN("/programs-page/bg%20%285%29%20%281%29.png"),
    borderColor: "#01a498",
    iconSrc: withCDN("/program-logo/robo_toys.svg"),
    imageSrc: withCDN("/programs-page/photo%20(6)%20(1).png"),
    AiGradientStart: "#069B93",
    AiGradientEnd: "#006C64",
  },
  {
    id: "builders",
    slug: "BIG_BUILDERS",
    title: "Big Builders",
    subtitle: "Welcome to A unique early-learning program",
    description:
      "where young minds explore the world of engineering and science through fun, hands-on building. Children learn core STEM principles by creating 3D models with specially designed building blocks — all through play, imagination, and teamwork.",
    ageRange: "4-6",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "45",
    lessonsTotal: "36 lessons",
    ribbon: withCDN("/Workshop/bg%20%285%29.png"),
    borderColor: "#F49800",
    iconSrc: withCDN("/program-logo/logo_big_builders.svg"),
    imageSrc: withCDN("/programs-page/photo%20(9)%20(1).png"),
    AiGradientStart: "#f39000",
    AiGradientEnd: "#ffed00",
  },
  {
    id: "smartivo",
    slug: "SMARTIVO",
    title: "Smartivo",
    subtitle: "Welcome to Your First Step into Coding",
    description:
      "where young children are introduced to the basics of programming through playful story-missions. Using colorful blocks and the GoAlgo app, kids make robots move, light up, and respond to commands.",
    ageRange: "4-6",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "45",
    lessonsTotal: "36 lessons",
    ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png"),
    borderColor: "#00AFE9",
    iconSrc: withCDN("/program-logo/logo_smartivo.svg"),
    imageSrc: withCDN("/programs-page/photo%20(10)%20(1).png"),
    AiGradientStart: "#0091d6",
    AiGradientEnd: "#61bae5",
  },
  {
    id: "algoC",
    slug: "ALGOC",
    title: "Algo C",
    subtitle: "Welcome to A hands-on learning experience",
    description:
      "designed to equip students with core skills in coding, robotics, AI, and problem-solving. Centered on C programming for robotics and embedded systems, the program uses practical challenges and interactive lessons for a tech-driven future.",
    ageRange: "13-18",
    createdFor: "Created for children",
    ageText: "age",
    lessonDurationText: "Lesson duration",
    durationUnit: "min",
    lessonDuration: "90",
    lessonsTotal: "36 lessons",
    ribbon: withCDN("/programs-page/bg%20%286%29%20%281%29.png"),
    borderColor: "#E89163",
    iconSrc: withCDN("/program-logo/logo_algo_c.svg"),
    imageSrc: withCDN("/programs-page/photo%20(11)%20(1).png"),
    AiGradientStart: "#dc4b63",
    AiGradientEnd: "#F4A261",
  },
];

function ProgramArticle({ program }: { program: ProgramCard }) {
  const learnMoreHref =
    program.language !== "en" && program.parentProgramsId
      ? detailHref(
          "/programs",
          program.parentProgramsId,
          program.slug
        )
      : detailHref("/programs", program.id, program.slug);

  return (
    <article
      id={program.title}
      className="relative bg-white rounded-4xl shadow-md md:h-80 xl:h-[368px] flex flex-col md:flex-row border md:overflow-visible overflow-hidden program-article"
      style={{ borderColor: program.borderColor }}
    >
      {/* Mobile header */}
      <div className="md:hidden flex items-center gap-2 px-3 pt-1">
        <div
          className="relative w-[100px] h-[117px] max-[433px]:h-[117px] max-[330px]:h-[110px] max-[330px]:w-[100px] flex items-center justify-center overflow-hidden"
          style={{
            backgroundImage: `url(${optimizedImage(program.ribbon, 384)})`,
            backgroundSize: "cover",
            backgroundPosition: "center bottom",
            top: "-4px",
          }}
        >
          <div className="relative w-[75px] h-[75px] mt-[-30px] bg-white rounded-[50%] img-mob">
            {program.iconSrc ? (
              <Image
                src={program.iconSrc}
                alt={program.title}
                fill
                className="object-contain"
              />
            ) : (
              <div className="w-full h-full flex items-center justify-center text-gray-300">
                <span className="text-[10px]">No Logo</span>
              </div>
            )}
          </div>
        </div>

        <div className="flex-1 flex flex-col justify-between text-[11px] leading-snug text-gray-800 mt-[-4px] w-[80%]">
          <h3
            className="text-[34px] md:text-[25px] lg:text-[54px] font-bold uppercase leading-none w-[80%] mb-3 max-[330px]:text-[26px] mob-subtitle"
            style={{ color: program.borderColor }}
          >
            {program.title}
          </h3>
        </div>
      </div>

      {/* Desktop ribbon */}
      <div className="md:w-[145px] xl:w-[220px] hidden md:flex md:flex-col md:px-4 ribbon-container">
        <div
          className="absolute top-[-2px] w-[200px] md:left-6 h-[400px] md:w-[130px] md:h-[370px] xl:w-[175px] xl:h-[424px] bg-cover bg-center bg-no-repeat flex flex-col items-center justify-start text-white gap-3 overflow-visible ribbon_bg"
          style={{
            backgroundImage: `url(${optimizedImage(program.ribbon, 384)})`,
          }}
        >
          <div className="flex flex-col items-center gap-3 md:gap-2 lg:gap-3 mt-6 lg:mt-4">
            <div className="relative w-14 h-14 md:w-28 md:h-28 lg:w-[122px] lg:h-[122px] xl:w-[135px] xl:h-[135px] shrink-0 bg-white rounded-[50%] logo-img">
              {program.iconSrc ? (
                <Image
                  src={program.iconSrc}
                  alt={program.title}
                  fill
                  className="object-cover"
                />
              ) : (
                <div className="w-full h-full flex items-center justify-center text-gray-300">
                  <span className="text-xs">No Logo</span>
                </div>
              )}
            </div>

            <div className="text-xs md:text-sm leading-snug w-full md:w-[115px] xl:w-[135px] !mx-auto mt-1 md:ml-[30px] xl:ml-4 xl:mt-3">
              <p className="opacity-80 text-body3-mob w-full !text-[12px] md:!text-[11px] xl:!text-[16px]">
                {program.createdFor}
              </p>
              <span className="font-bold text-base md:text-lg text-body3-mob xl:text-[30px] xl:leading-[32px] p-range">
                {program.ageRange}
              </span>
              <span className="text-body3-mob lg:text-[16px]">
                {" "}{program.ageText}
              </span>
            </div>

            <div className="w-full text-xs md:text-lg leading-snug mt-2 md:w-[114px] xl:w-[135px] !mx-auto md:ml-[30px] xl:ml-4">
              <p className="opacity-80 text-[12px] w-full whitespace-nowrap md:!text-[11px] xl:!text-[16px]">
                {program.lessonDurationText}
              </p>
              <span className="font-bold md:text-lg text-body3-mob xl:text-[30px] xl:leading-[32px] p-duration">
                {program.lessonDuration}
              </span>
              <span className="text-body3-mob lg:text-[16px]">
                {" "}{program.durationUnit}
              </span>
              <p className="mt-1 text-body3-mob font-bold text-white leading-tight">
                {program.lessonsTotal}
              </p>
            </div>
          </div>
        </div>
      </div>

      {/* Center content */}
      <div className="flex-1 px-5 md:px-6 md:py-2 lg:px-0 xl:px-1 2xl:px-3 flex flex-col md:pr-[280px] lg:pr-[260px] xl:pr-[540px] 2xl:pr-[550px] h-full md:max-h-[368px] max-[330px]:px-3 mt-[-10px] md:mt-0 all-programs-content-box">
        <div className="flex-1 pr-2 mt-1 mb-3">
          <div className="min-h-full flex flex-col justify-center">
            <h3
              className="text-[30px] md:text-[30px] xl:text-[50px] font-bold uppercase leading-tight xl:leading-none hidden md:block min-[1600px]:w-[89%] program_card_heading"
              style={{ color: program.borderColor }}
            >
              {program.title}
            </h3>

            <div className="mt-2">
              <h3 className="text-[20px] md:text-[18px] xl:text-[20px] 2xl:text-[20px] uppercase leading-tight text-[#58585A] max-[767px]:font-semibold">
                {renderSubtitleWithAIGradient(
                  program.subtitle,
                  program.AiGradientStart,
                  program.AiGradientEnd
                )}
              </h3>

              <div className="block md:hidden border-b border-t border-[#CACACA] mt-2 mb-3">
                <div className="flex flex-row gap-4 py-3">
                  <div className="w-[41%]">
                    <p className="opacity-80 text-[16px] mb-1">
                      Created for
                    </p>
                    <div className="flex items-start flex-col gap-0 max-[330px]:gap-1">
                      <span
                        className="font-bold text-[30px] leading-none max-[400px]:text-[30px] max-[360px]:text-[29px]"
                        style={{ color: program.borderColor }}
                      >
                        {program.ageRange}
                      </span>
                      <p
                        className="text-[16px]"
                        style={{ color: program.borderColor }}
                      >
                        {program.ageText}
                      </p>
                    </div>
                  </div>

                  <div className="text-left">
                    <p className="opacity-80 text-[16px] mb-1">
                      Duration
                    </p>
                    <div className="flex flex-col gap-1">
                      <div className="flex items-end gap-2 max-[330px]:gap-1">
                        <span
                          className="font-bold text-[30px] leading-none max-[360px]:text-[29px]"
                          style={{ color: program.borderColor }}
                        >
                          {program.lessonDuration}
                        </span>
                        <span
                          className="text-[16px]"
                          style={{ color: program.borderColor }}
                        >
                          {program.durationUnit}
                        </span>
                      </div>
                      <p
                        className="opacity-80 text-[16px]"
                        style={{ color: program.borderColor }}
                      >
                        ({program.lessonsTotal})
                      </p>
                    </div>
                  </div>
                </div>
              </div>

              <p className="mt-3 2xl:mt-4 text-[16px] md:text-body3-mob xl:text-[16px] 2xl:text--[16px] leading-relaxed max-w-full md:max-w-[480px] xl:max-w-[600px] 2xl:max-w-[700px] text-[#58585A] min-[1600px]:!text-[16px] min-[1600px]:!leading-[24px] wrap-break-word program-discription md:overflow-y-auto md:scroll-thin md:h-[110px] md:pr-2">
                {program.description}
              </p>
            </div>

            <div className="mt-4">
              <LanguageAwareLink
                href={learnMoreHref}
                className="inline-flex items-center justify-center gap-2 w-40 md:w-50 lg:w-50 xl:w-60 2xl:w-60 xl:py-2 xl:px-1 rounded-full border border-[#0097DC] px-2 py-2 text-body4-desktop xl:text-body4-desktop 2xl:text-[18px] font-semibold bg-[#0097DC] text-white hover:bg-[#0097DC] hover:shadow-[10px_14px_14px_#0000000D] active:bg-[#0084C1] transition-colors cursor-pointer max-[1024px]:w-[260px] max-[500px]:w-full"
              >
                <Image
                  src={withCDN("/programs-page/AllPrograms/Vector.svg")}
                  alt="arrow"
                  width={26}
                  height={26}
                  className="transition-all"
                  unoptimized
                />
                <span>LEARN MORE</span>
              </LanguageAwareLink>
            </div>
          </div>
        </div>
      </div>

      {/* Right image */}
      <div className="relative w-[98%] sm:w-[98%] sm:right-0 right-0 mx-auto mt-2 xl:right-8 h-[217px] rounded-[30px] overflow-hidden md:absolute md:top-1/2 md:right-2 md:-translate-y-1/2 md:w-[257px] md:mx-0 md:mt-0 mb-1 sm:mb-4 md:h-[360px] lg:h-[350px] xl:w-[506px] xl:h-[403px] card-image">
        {program.imageSrc ? (
          <Image
            src={program.imageSrc}
            alt={program.title}
            fill
            className="object-cover"
          />
        ) : (
          <div className="w-full h-full bg-gray-100 flex items-center justify-center text-gray-400">
            <span>No Image</span>
          </div>
        )}
      </div>
    </article>
  );
}

interface AllProgramsProps {
  allProgramData?: ProgramsPageSection;
  generalSettings?: any;
  programs?: any[];
  isLoading?: boolean;
}

export default function AllPrograms({
  allProgramData,
  generalSettings,
  programs = [],
  isLoading = false,
}: AllProgramsProps) {
  const [currentIndex, setCurrentIndex] = useState(0);
  const [visibleCount, setVisibleCount] = useState(5);
  const [programsList, setProgramsList] =
    useState<ProgramCard[]>(FALLBACK_PROGRAMS);

  const containerRef = useRef<HTMLDivElement | null>(null);
  const swiperRef = useRef<SwiperType | null>(null);

  const { currentLanguage } = useLanguage();

  useEffect(() => {
    if (Array.isArray(programs) && programs.length > 0) {
      const mappedPrograms: ProgramCard[] = programs.map(
        (program: any) => {
          const staticAttrs = getStaticAttributesBySlug(program.slug);

          return {
            id: program.id,
            slug: program.slug,
            title: program.title,
            subtitle: program.sub_heading || program.title,
            description: program.description || "",
            ageRange: program.age_range || "",
            createdFor:
              program.created_for ||
              program.program_details?.created_for ||
              "Created for children",
            ageText: program.age_text || "age",
            lessonDurationText:
              program.lesson_duration_text || "Lesson duration",
            durationUnit: program.duration_text || "min",
            lessonDuration: program.duration || "",
            lessonsTotal: `${program.no_of_lessons || "0"} ${
              program.no_of_lessons === 1 ? "lesson" : ""
            }`,
            ribbon: staticAttrs?.ribbon || "",
            borderColor: staticAttrs?.borderColor || "",
            iconSrc: program.program_icon
              ? withCDN(program.program_icon)
              : staticAttrs?.iconSrc || "",
            imageSrc: program.header_image
              ? withCDN(program.header_image)
              : staticAttrs?.imageSrc || "",
            parentProgramsId: program.parent_programs_id,
            language: program.language,
            AiGradientStart:
              program.AiGradientStart ||
              staticAttrs?.AiGradientStart ||
              "#4B134A",
            AiGradientEnd:
              program.AiGradientEnd ||
              staticAttrs?.AiGradientEnd ||
              "#993F98",
          };
        }
      );

      setProgramsList(mappedPrograms);
    } else if (!isLoading) {
      setProgramsList(FALLBACK_PROGRAMS);
    }
  }, [programs, isLoading]);

  const heading = allProgramData?.heading || "ALL YE PROGRAMS";
  const showMoreText = allProgramData?.showMoreText || "See more";

  // Keep the active slide index within the updated list.
  useEffect(() => {
    if (currentIndex >= programsList.length) {
      setCurrentIndex(Math.max(0, programsList.length - 1));
    }

    const swiper = swiperRef.current;

    if (swiper && !swiper.destroyed) {
      const safeIndex = Math.min(
        currentIndex,
        Math.max(0, programsList.length - 1)
      );

      if (swiper.activeIndex !== safeIndex) {
        swiper.slideTo(safeIndex, 0);
      }
    }
  }, [programsList, currentIndex]);

  const goToSlide = (index: number) => {
    const swiper = swiperRef.current;

    if (!swiper || swiper.destroyed) return;

    const safeIndex = Math.max(
      0,
      Math.min(index, programsList.length - 1)
    );

    swiper.slideTo(safeIndex, 300);
    setCurrentIndex(safeIndex);
  };

  const handleShowMore = () => {
    setVisibleCount((prev) =>
      Math.min(prev + 3, programsList.length)
    );
  };

  const handleSlideChange = (swiper: SwiperType) => {
    if (swiper.destroyed) return;
    setCurrentIndex(swiper.realIndex ?? swiper.activeIndex);
  };

  const visiblePrograms = programsList.slice(0, visibleCount);
  const hasMore = visibleCount < programsList.length;

  return (
    <section
      ref={containerRef}
      className="relative w-full overflow-visible -mt-140 h-fit xl:-mt-75 md:-mt-135 lg:-mt-80 z-30 pt-28 md:pt-32 pb-16 xl:pb-0"
      id="all-program"
    >
      {/* Curved background */}
      <div className="absolute inset-0 w-full h-full -z-10 overflow-hidden">
        <div className="absolute top-0 left-0 w-full hidden lg:block">
          <Image
            src={withCDN("/programs-page/AllPrograms/allPrograms.svg")}
            alt="Curved background"
            width={1920}
            height={1080}
            className="w-full h-auto"
            priority
            unoptimized
          />
        </div>

        <div className="absolute top-0 left-0 w-full hidden md:block lg:hidden">
          <Image
            src="https://yefranchisees.b-cdn.net/frontend/allProgramsTab.svg"
            alt="Curved background for tablet"
            width={834}
            height={1080}
            className="w-full h-auto"
            priority
            unoptimized
          />
        </div>

        <div className="absolute top-8 left-0 w-full block md:hidden mobile-bg">
          <Image
            src={withCDN("/programs-page/AllPrograms/allPrograms.svg")}
            alt="Curved background for mobile"
            width={430}
            height={1080}
            className="w-full h-auto"
            priority
            unoptimized
          />
        </div>
      </div>

      {/* Content */}
      <div className="relative z-20 max-w-[1300px] mx-auto w-full px-4 md:px-10 lg:px-18 xl:px-0 mb-10 sm:mb-0 md:pb-1 lg:mb-0">
        <h2 className="text-[30px] xl:text-[50px] text-[#58585A] md:text-[32px] font-bold leading-tight tracking-wide mb-5 mt-[-20px]">
          {heading}
        </h2>

        {/* Mobile slider */}
        <div className="md:hidden">
          <div className="max-w-full mx-auto">
            {isLoading ? (
              <div className="space-y-6">
                {[1, 2].map((idx) => (
                  <WorkshopCardSkeleton key={idx} />
                ))}
              </div>
            ) : (
              <Swiper
                // Native touch swiping works better on iOS than Mousewheel.
                speed={300}
                initialSlide={0}
                slidesPerView={1}
                slidesPerGroup={1}
                spaceBetween={16}
                loop={false}
                grabCursor={false}
                allowTouchMove={true}
                simulateTouch={true}
                touchRatio={1}
                touchAngle={45}
                threshold={5}
                resistance={true}
                resistanceRatio={0.65}
                touchStartPreventDefault={false}
                touchMoveStopPropagation={false}
                preventClicks={true}
                preventClicksPropagation={true}
                passiveListeners={true}
                watchOverflow={true}
                onSwiper={(swiper) => {
                  swiperRef.current = swiper;
                  setCurrentIndex(swiper.realIndex ?? 0);
                }}
                onSlideChange={handleSlideChange}
                onTouchEnd={(swiper) => {
                  requestAnimationFrame(() => {
                    if (!swiper.destroyed) {
                      setCurrentIndex(
                        swiper.realIndex ?? swiper.activeIndex
                      );
                    }
                  });
                }}
                onBeforeDestroy={(swiper) => {
                  if (swiperRef.current === swiper) {
                    swiperRef.current = null;
                  }
                }}
                className="all-programs-swiper"
              >
                {programsList.map((program) => (
                  <SwiperSlide
                    key={program.id}
                    className="program-slide"
                  >
                    <ProgramArticle program={program} />
                  </SwiperSlide>
                ))}
              </Swiper>
            )}
          </div>

          {/* Custom dots */}
          {!isLoading && (
            <div className="flex justify-center mt-4">
              {programsList.map((program, idx) => (
                <button
                  key={program.id}
                  type="button"
                  onClick={() => goToSlide(idx)}
                  aria-label={`Go to ${program.title}`}
                  aria-current={idx === currentIndex ? "true" : undefined}
                  className="w-[40px] h-[40px] flex items-center justify-center"
                >
                  <span
                    className={`w-[16px] h-[16px] rounded-full transition-colors duration-200 ${
                      idx === currentIndex
                        ? "bg-[#00AEEF]"
                        : "bg-[#00AEEF]/40"
                    }`}
                  />
                </button>
              ))}
            </div>
          )}
        </div>

        {/* Tablet and desktop: original stacked layout */}
        <div className="space-y-10 md:space-y-20 xl:space-y-20 hidden md:block">
          {isLoading ? (
            [1, 2, 3].map((idx) => (
              <WorkshopCardSkeleton key={idx} />
            ))
          ) : (
            <>
              {visiblePrograms.map((program) => (
                <ProgramArticle key={program.id} program={program} />
              ))}

              {hasMore && (
                <div className="flex justify-center my-8 md:my-10 more-button">
                  <button
                    type="button"
                    onClick={handleShowMore}
                    className="text-[#00AEEF] text-sm font-semibold tracking-wide uppercase hover:underline transition-all cursor-pointer"
                  >
                    {showMoreText.toUpperCase()}
                  </button>
                </div>
              )}
            </>
          )}
        </div>
      </div>
    </section>
  );
}
