import { useRef } from 'react';

import type { CSSProperties, MutableRefObject, ReactNode } from 'react';
import type { CarouselApi } from './useCarousel';

import Box from '~/src/components/Box';
import useCarousel from './useCarousel';

export type { CarouselApi };

const Carousel = <TItem,>({
  renderItem,
  items,
  style,
  onChange = () => {},
  apiRef,
}: {
  apiRef: MutableRefObject<CarouselApi | null>;
  items: TItem[];
  renderItem: (params: { item: TItem }) => ReactNode;
  style?: CSSProperties;
  onChange?: (index: number) => void;
}) => {
  const listElRef = useRef<HTMLElement>(null);
  const rootElRef = useRef<HTMLDivElement>(null);
  const listWidth = `${100 * items.length}.03%`;
  const itemWidth = `${100 / items.length}%`;

  const carousel = useCarousel({
    rootElRef,
    listElRef,
    onChange,
    totalItems: items.length,
  });

  apiRef.current = carousel;

  return (
    <>
      <div
        style={{
          ...style,
          overflow: 'hidden',
        }}
      >
        {/* the root carousel container must not have any border/padding styling to ensure accurate measurements */}
        <div ref={rootElRef} data-testid="carouselSwiper">
          <Box
            tag="ul"
            nodeRef={listElRef}
            flexBox
            width={listWidth}
            style={{
              willChange: 'transform',
            }}
          >
            {items.map((item, index) => {
              return (
                <li
                  key={index}
                  style={{
                    width: itemWidth,
                    flexShrink: 0,
                  }}
                >
                  {renderItem({ item })}
                </li>
              );
            })}
          </Box>
        </div>
      </div>
    </>
  );
};

export default Carousel;
