import clsx from 'clsx';
import { createContext, useCallback, useEffect, useState } from 'react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';
import { useIsClient } from 'usehooks-ts';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import useAutoplayCarousel from '@/hooks/useAutoplayCarousel';
import { ChevronLeftIcon, ChevronRightIcon } from '@/icons';

export const ExpandedContent = () => {};

export const useHeroCarousel = ({
  autoplayDelay,
  loop,
  itemLength,
  controlledCollapsed,
  onCollapseChange,
}: {
  autoplayDelay: number;
  loop: boolean;
  itemLength: number;
  controlledCollapsed?: boolean;
  onCollapseChange?: (collapsed: boolean) => void;
}) => {
  const [internalCollapsed, setInternalCollapsed] = useState(false);

  // Use controlled state if provided, otherwise use internal state
  const isCollapsed =
    controlledCollapsed !== undefined ? controlledCollapsed : internalCollapsed;

  const setIsCollapsed = useCallback(
    (collapsed: boolean) => {
      if (controlledCollapsed !== undefined) {
        // In controlled mode, call the parent callback
        onCollapseChange?.(collapsed);
      } else {
        // In uncontrolled mode, update internal state
        setInternalCollapsed(collapsed);
      }
    },
    [controlledCollapsed, onCollapseChange]
  );
  const {
    emblaRef,
    stopAutoplay,
    startAutoplay,
    Indicators,
    goToPrevious,
    goToNext,
  } = useAutoplayCarousel({
    autoplayDelay,
    loop,
    itemLength,
  });
  return {
    isCollapsed,
    setIsCollapsed,
    emblaRef,
    stopAutoplay,
    startAutoplay,
    Indicators,
    goToPrevious,
    goToNext,
  };
};

export const HeroCarouselContext = createContext<{
  isCollapsed: boolean;
  setIsCollapsed: (isCollapsed: boolean) => void;
  Indicators: (props: {
    className?: string;
    buttonClassName?: string;
  }) => React.ReactNode;
  goToPrevious: () => void;
  goToNext: () => void;
}>({
  isCollapsed: false,
  setIsCollapsed: () => {},
  Indicators: () => <></>,
  goToPrevious: () => {},
  goToNext: () => {},
});

export const HeroCarouselNavigationButton = ({
  onClick,
  icon,
  ariaLabel,
  buttonClassName,
  buttonVariant = ButtonVariant.LightGlass,
  buttonShape = ButtonShape.Pill,
  buttonSize = ButtonSize.Micro,
  className,
}: {
  onClick: () => void;
  icon: React.ComponentType<{ className?: string }>;
  ariaLabel: string;
  buttonClassName?: string;
  buttonVariant?: ButtonVariant;
  buttonShape?: ButtonShape;
  buttonSize?: ButtonSize;
} & React.HTMLAttributes<HTMLDivElement>) => {
  return (
    <div
      className={twMerge(
        'flex items-center justify-center',
        'transition-all duration-300 ease-out',
        'max-sm:hidden',
        // Hide by default, show on carousel group hover
        'pointer-events-none opacity-0',
        'group-hover/carousel:pointer-events-auto group-hover/carousel:translate-x-0 group-hover/carousel:opacity-100',
        className
      )}
    >
      <Button
        className={buttonClassName}
        variant={buttonVariant}
        shape={buttonShape}
        size={buttonSize}
        icon={icon}
        onClick={onClick}
        aria-label={ariaLabel}
      />
    </div>
  );
};

type HeroCarouselProps = {
  autoplayDelay?: number;
  loop?: boolean;
  items: React.ComponentType[];
  localStorageKey?: string;
  /** Controlled collapsed state - when provided, overrides internal state */
  collapsed?: boolean;
  /** Callback when collapse state changes */
  onCollapseChange?: (collapsed: boolean) => void;
} & React.HTMLAttributes<HTMLDivElement>;

export const HeroCarousel: React.FC<HeroCarouselProps> = (props) => {
  const {
    autoplayDelay = 5000,
    loop = true,
    items,
    localStorageKey,
    collapsed: controlledCollapsed,
    onCollapseChange,
    className,
  } = props;

  const {
    isCollapsed,
    setIsCollapsed,
    emblaRef,
    stopAutoplay,
    startAutoplay,
    Indicators,
    goToPrevious,
    goToNext,
  } = useHeroCarousel({
    // for dev: change this to a large number to "disable" autoplay
    autoplayDelay,
    loop,
    itemLength: items.length,
    controlledCollapsed,
    onCollapseChange,
  });

  const { t } = useTranslation();

  const canShowNavigationButtons = !isCollapsed && items.length > 1;
  const [showNavigationButtons, setShowNavigationButtons] = useState(
    canShowNavigationButtons
  );

  useEffect(() => {
    // Delay navigation buttons to give collapse transition time to finish
    if (canShowNavigationButtons) {
      const timeout = setTimeout(() => {
        setShowNavigationButtons(true);
      }, 250);
      return () => {
        clearTimeout(timeout);
      };
    }

    setShowNavigationButtons(canShowNavigationButtons);
  }, [canShowNavigationButtons]);

  const isClient = useIsClient();
  useEffect(() => {
    if (localStorageKey && isClient) {
      const savedState = localStorage.getItem(localStorageKey);
      if (savedState !== null) {
        setIsCollapsed(savedState === 'true');
      }
    }
  }, [isClient, localStorageKey, setIsCollapsed]);

  return (
    <div
      className={twMerge(
        clsx('relative', {
          'group/carousel': showNavigationButtons,
        }),
        className
      )}
      onMouseEnter={stopAutoplay}
      onMouseLeave={startAutoplay}
    >
      <div
        className='relative w-full overflow-clip rounded-2xl bg-background-primary'
        ref={emblaRef}
      >
        <HeroCarouselContext.Provider
          value={{
            isCollapsed,
            setIsCollapsed,
            Indicators,
            goToPrevious,
            goToNext,
          }}
        >
          <div className='flex flex-row items-stretch'>
            {items.map((item, index) => (
              <div key={index} className='min-w-0 flex-[0_0_100%]'>
                {React.createElement(item)}
              </div>
            ))}
          </div>
        </HeroCarouselContext.Provider>
      </div>
      {!isCollapsed && (
        <Indicators className='pt-1' buttonClassName='h-[0.5px]' />
      )}
      {showNavigationButtons && goToPrevious ? (
        <HeroCarouselNavigationButton
          onClick={goToPrevious}
          icon={ChevronLeftIcon}
          ariaLabel={t('cta.prev')}
          className='absolute inset-y-0 left-2 -translate-x-2'
        />
      ) : null}
      {showNavigationButtons && goToNext ? (
        <HeroCarouselNavigationButton
          onClick={goToNext}
          icon={ChevronRightIcon}
          ariaLabel={t('cta.next')}
          className='absolute inset-y-0 right-2 translate-x-2'
        />
      ) : null}
    </div>
  );
};

export default HeroCarousel;
