'use client';
import { useEffect, useRef } from 'react';
import Swiper from 'swiper';
import {
  Pagination,
  Navigation,
  EffectCreative,
  EffectCards,
  Controller,
  Keyboard,
  Scrollbar as ScrollbarModule
} from 'swiper/modules';
import cn from '@/lib/merge-clsx';
import Icon from '@/components/base/Icon';
import Container from '@/components/layout/Container';
import Scrollbar from './Scrollbar';
import type { Swiper as SwiperType } from 'swiper';
import 'swiper/css';
import 'swiper/css/effect-creative';
import 'swiper/css/scrollbar';
import './styles.css';

import { ScrollbarOptions, SwiperOptions } from 'swiper/types';
import { IconProps } from '@/components/base/Icon';

export type SwiperElementProps = {
  children: React.ReactNode;
  dir?: 'rtl' | 'ltr';
  className?: string;
  isOverflowVisible?: boolean;
  options?: Omit<SwiperOptions, 'pagination' | 'navigation'> & {
    pagination?: {
      variant: 'primary' | 'secondary' | 'light' | 'dark';
      position?: 'bottom' | 'overlap';
      align?: 'start' | 'center' | 'end';
      bullet?: 'small' | 'large';
      type?: 'bullets' | 'fraction';
      className?: string;
    };
    navigation?: {
      variant: 'primary' | 'secondary' | 'light' | 'dark';
      nextClassName?: string;
      prevClassName?: string;
    };
  };
};

export type SwiperElementPropsWithAs<
  T extends React.ElementType = React.ElementType
> = SwiperElementProps &
  React.ComponentPropsWithoutRef<T> & {
    as?: T;
  };

export type SwiperSlideProps = {
  children: React.ReactNode;
  className?: string;
};

type SwiperElementRef = {
  swiper?: SwiperType;
} & HTMLDivElement;

export interface ScrollbarProps {
  swiperRef: React.RefObject<SwiperElementRef>;
  isDragging: React.RefObject<boolean>;
}

const SwiperElement: React.FC<SwiperElementPropsWithAs> & {
  Slide: React.FC<SwiperSlideProps>;
} = ({
  as: Component = 'div',
  dir = 'ltr',
  className,
  options = {},
  children,
  ...props
}) => {
  const swiperRef = useRef<SwiperElementRef>(null);
  const paginationRef = useRef<HTMLDivElement>(null);
  const nextRef = useRef<HTMLDivElement>(null);
  const prevRef = useRef<HTMLDivElement>(null);
  const isDragging = useRef(false);

  useEffect(() => {
    if (swiperRef.current) {
      const swiper = new Swiper(swiperRef.current, {
        ...options,
        modules: [
          Pagination,
          Navigation,
          EffectCreative,
          EffectCards,
          Controller,
          Keyboard,
          ScrollbarModule
        ],
        keyboard: true,
        pagination: options.pagination
          ? { el: paginationRef.current, clickable: true }
          : false,
        navigation: options.navigation
          ? { nextEl: nextRef.current, prevEl: prevRef.current }
          : false
      });
      swiper.on('scrollbarDragMove', (swiper, event) => {
        isDragging.current = true;
      });
      return () => {
        swiper.destroy();
      };
    }
  }, [dir, options]);

  const paginationClasses = options.pagination
    ? cn('swiper-pagination flex p-6 gap-1', options.pagination.className, {
        'swiper-pagination-primary':
          options.pagination.variant === 'primary' &&
          options.pagination.type !== 'fraction',
        'swiper-pagination-secondary':
          options.pagination.variant === 'secondary' &&
          options.pagination.type !== 'fraction',
        'swiper-pagination-fraction': options.pagination.type === 'fraction',
        'swiper-pagination-light': options.pagination.variant === 'light',
        'swiper-pagination-dark': options.pagination.variant === 'dark',
        'justify-start': options.pagination.align === 'start',
        'justify-end': options.pagination.align === 'end',
        'justify-center': options.pagination.align === 'center',
        'absolute inset-x-0 bottom-0 z-10':
          options.pagination.position === 'overlap',
        'swiper-pagination-large': options.pagination?.bullet === 'large'
      })
    : '';

  const navigationClasses = cn(
    'absolute z-10 top-1/2 -translate-y-1/2 cursor-pointer text-3xl',
    {
      'text-primary':
        options.navigation?.variant === 'primary' ||
        !options.navigation?.variant,
      'text-secondary': options.navigation?.variant === 'secondary',
      'text-background': options.navigation?.variant === 'light',
      'text-foreground': options.navigation?.variant === 'dark'
    }
  );

  const prevIcon = cn({
    'left-arrow': dir === 'ltr',
    'right-arrow': dir === 'rtl'
  }) as IconProps['name'];

  const nextIcon = cn({
    'right-arrow': dir === 'ltr',
    'left-arrow': dir === 'rtl'
  }) as IconProps['name'];

  return (
    <div key={dir} dir={dir}>
      <Component className={cn('relative', className)} {...props}>
        <div
          className={`swiper ${props?.isOverflowVisible ? '!overflow-visible' : ''}`}
          dir={dir}
          ref={swiperRef}>
          <div className="swiper-wrapper">{children}</div>
        </div>
        {options.navigation && (
          <div
            ref={prevRef}
            className={cn(
              navigationClasses,
              options.navigation.prevClassName || 'start-2'
            )}>
            <Icon name={prevIcon} className="!font-bold" />
          </div>
        )}
        {options.navigation && (
          <div
            ref={nextRef}
            className={cn(
              navigationClasses,
              options.navigation.nextClassName || 'end-2'
            )}>
            <Icon name={nextIcon} className="!font-bold" />
          </div>
        )}
      </Component>
      {options.scrollbar &&
        (() => {
          const el =
            typeof options.scrollbar === 'object' &&
            typeof options.scrollbar.el === 'string'
              ? options.scrollbar.el
              : null;
          const isClassSelector = el?.startsWith('.');
          const isIdSelector = el?.startsWith('#');
          const extractedClass = isClassSelector ? el?.slice(1) : '';
          const extractedId = isIdSelector ? el?.slice(1) : undefined;
          return (
            <div
              className={`relative w-full mt-14 mb-8 bg-white bg-opacity-20 h-px rounded-full ${extractedClass} `}
              id={extractedId}>
              <Scrollbar isDragging={isDragging} swiperRef={swiperRef as any} />
            </div>
          );
        })()}
      {options.pagination && (
        <Container className="relative">
          <div ref={paginationRef} className={paginationClasses} />
        </Container>
      )}
    </div>
  );
};

const Slide: React.FC<SwiperSlideProps> = ({ className, children }) => {
  return <div className={cn('swiper-slide', className)}>{children}</div>;
};

SwiperElement.Slide = Slide;
export default SwiperElement;
