"use client";

import cx from "classnames";
import React, { ReactNode, useId } from "react";
import { useStatic } from "@/utils/hooks";
import { Container } from "../Container";
import { Controls } from "../Controls";
import CarouselHeroStatic from "./CarouselHero.static";
import { CarouselHeroItem } from "./CarouselHeroItem";
import {
  CLASS_NAVIGATION,
  CLASS_NEXT,
  CLASS_PAGINATION,
  CLASS_PLAY_PAUSE,
  CLASS_PREV,
  CLASS_ROOT,
  CLASS_TAB,
  CLASS_TABS,
  CLASS_TRACK,
  CLASS_VIEWPORT,
  CLASS_VIEWPORT_WRAPPER,
} from "./constants";

function getCarouselHeroSlides(children: ReactNode): React.ReactElement[] {
  const slides: React.ReactElement[] = [];

  React.Children.forEach(children, (child) => {
    if (!React.isValidElement(child)) return;

    if (child.type === React.Fragment) {
      slides.push(
        ...getCarouselHeroSlides(
          (child.props as { children?: ReactNode }).children,
        ),
      );
      return;
    }

    slides.push(child);
  });

  return slides;
}

interface TabItem {
  label: string;
  id?: string;
  [key: string]: any;
}

type CarouselHeroSlideElement = React.ReactElement<Record<string, any>>;

interface CarouselHeroProps {
  className?: string;
  swiperOptions?: Record<string, any>;
  children?: ReactNode;
  tabs?: TabItem[];
  interval?: number;
  enableAutoplay?: boolean;
  [key: string]: any;
}

const CarouselHero: React.FC<CarouselHeroProps> = ({
  className,
  swiperOptions,
  children,
  tabs = [],
  interval,
  enableAutoplay = false,
  ...other
}) => {
  const [carouselRef] = useStatic(CarouselHeroStatic);

  const classes = cx(CLASS_ROOT, className);
  const generatedId = `carousel-hero-${useId().replace(/:/g, "-")}`;
  const carouselId =
    typeof other.id === "string" && other.id ? other.id : generatedId;
  const slideItems = getCarouselHeroSlides(
    children,
  ) as CarouselHeroSlideElement[];
  const hasTabs = tabs.length > 0 && slideItems.length > 0;
  const getTabId = (tab: TabItem | undefined, index: number) =>
    typeof tab?.id === "string" && tab.id
      ? tab.id
      : `${carouselId}-tab-${index}`;
  const getPanelId = (
    slide: CarouselHeroSlideElement | undefined,
    index: number,
  ) =>
    slide && typeof slide.props.id === "string" && slide.props.id
      ? slide.props.id
      : `${carouselId}-panel-${index}`;

  const elementClasses = {
    prev: CLASS_PREV,
    next: CLASS_NEXT,
    playPause: CLASS_PLAY_PAUSE,
    tabs: CLASS_TABS,
    tab: CLASS_TAB,
    pagination: CLASS_PAGINATION,
  };

  const forwardedSwiperOptions = (() => {
    if (!swiperOptions) return undefined;
    if (enableAutoplay || !("autoplay" in swiperOptions)) return swiperOptions;

    const { autoplay: _autoplay, ...rest } = swiperOptions;

    return Object.keys(rest).length > 0 ? rest : undefined;
  })();

  const hasAutoplay =
    enableAutoplay &&
    (((swiperOptions?.autoplay &&
      typeof swiperOptions.autoplay === "object" &&
      (swiperOptions.autoplay as any).delay >= 1000) as boolean) ||
      !!(interval && interval >= 1000));

  const playPauseIcon = "pause";
  const tabSlides = slideItems.map((slide, index) => {
    if (!hasTabs) {
      return slide;
    }

    const tabId = getTabId(tabs[index], index);
    const panelId = getPanelId(slide, index);

    return React.cloneElement(slide as CarouselHeroSlideElement, {
      id: panelId,
      role: "tabpanel",
      "aria-labelledby": tabId,
    });
  });

  return (
    <div
      className={classes}
      ref={carouselRef}
      data-carousel-hero
      {...(enableAutoplay && interval && interval >= 1000
        ? { "data-interval": interval }
        : {})}
      {...(forwardedSwiperOptions
        ? { "data-swiper-options": JSON.stringify(forwardedSwiperOptions) }
        : {})}
      {...other}
    >
      <div className={CLASS_VIEWPORT_WRAPPER}>
        <div className={CLASS_VIEWPORT}>
          <div className={CLASS_TRACK}>{tabSlides}</div>
        </div>
      </div>

      {/* Controls container */}
      <Container className="d-flex">
        {/* Tab navigation */}
        {hasTabs && (
          <div className={elementClasses.tabs} role="tablist">
            {tabs.map((tab, index) => (
              <button
                id={getTabId(tab, index)}
                key={index}
                type="button"
                className={elementClasses.tab}
                role="tab"
                aria-controls={getPanelId(slideItems[index], index)}
                aria-selected={index === 0 ? "true" : "false"}
                tabIndex={index === 0 ? 0 : -1}
              >
                {tab.label}
              </button>
            ))}
          </div>
        )}

        {/* Pagination dots for mobile */}
        <div role="tablist" className={elementClasses.pagination} />

        {/* Navigation controls */}
        <div className={CLASS_NAVIGATION}>
          <Controls
            className={elementClasses.prev}
            icon="chevron-left"
            aria-label="Predchádzajúci snímok"
          />

          <Controls
            className={elementClasses.next}
            icon="chevron-right"
            aria-label="Nasledujúci snímok"
          />

          {/* Only show play/pause button if autoplay is configured */}
          {hasAutoplay && (
            <Controls
              className={elementClasses.playPause}
              icon={playPauseIcon}
              aria-label="Pozastaviť/Spustiť automatické prehrávanie"
            />
          )}
        </div>
      </Container>
    </div>
  );
};

CarouselHero.displayName = "CarouselHero";

export type { CarouselHeroProps, TabItem };
export { CarouselHero, CarouselHeroItem };
