import { memo, useCallback } from 'react';

import type { FC } from 'react';
import type { HorizontalItemProps } from './HorizontalItem';

import Box from '~/src/components/Box';
import HorizontalScroller from '~/src/components/Scroller2/HorizontalScroller';
import useIsLargeScreen from '~/src/hooks/useIsLargeScreen';
import SectionTitle from '../SectionTitle';
import HorizontalItem from './HorizontalItem';

export interface HorizontalItemsSectionProps {
  title: string;
  items: (HorizontalItemProps & { key: string | number })[];
  testId?: string;
  backgroundColor?: string;
}

const HorizontalItemsSection: FC<HorizontalItemsSectionProps> = ({
  title,
  items,
  backgroundColor,
}) => {
  const isLargeScreen = useIsLargeScreen();
  const ItemList = isLargeScreen ? ItemListLarge : ItemListSmall;

  // don't render anything if there are no items
  if (!items.length) {
    return null;
  }

  return (
    <div>
      <SectionTitle margin="0 0 2.3rem" text={title} />
      <Box positionRelative>
        <ItemList items={items} backgroundColor={backgroundColor} />
      </Box>
    </div>
  );
};

const ItemListLarge = memo<
  Pick<HorizontalItemsSectionProps, 'items' | 'backgroundColor'>
>(({ items = [], backgroundColor }) => {
  const MAX_ITEMS_PER_ROW = 4;

  // This logic ensures the list items and the parent scroll-content-container
  // are the right size. When the items fit within one row we want them to flex
  // to fill the container, but when they overflow and require scroll we need
  // to size them differently to maintain the same size.
  const totalItems = items.length;
  const itemsPerRow = Math.min(totalItems, MAX_ITEMS_PER_ROW);
  const percentWidthRelativeToScroller = 100 / itemsPerRow;
  const fullRows = Math.floor(totalItems / itemsPerRow);
  const totalInLastRow = totalItems % itemsPerRow;
  let contentWidthRelativeToScroller = fullRows;

  if (totalInLastRow) {
    contentWidthRelativeToScroller += totalInLastRow / itemsPerRow;
  }

  const itemWidthPercent =
    percentWidthRelativeToScroller / contentWidthRelativeToScroller;

  const totalTextLines = items[0].textLineClamp ?? 2;
  const arrowOffsetY = totalTextLines * 20;

  return (
    <div
      style={{
        position: 'relative',
        margin: '-.8rem -.55rem',
        padding: '0 1.2rem',
      }}
    >
      <HorizontalScroller
        contentStyle={{
          width: `${contentWidthRelativeToScroller * 100}%`,
        }}
        overflowStyle="outside"
        gradientColor={backgroundColor}
        arrowOffsetY={arrowOffsetY}
        centerContent
        renderContent={useCallback(() => {
          return items.map(({ key, ...item }) => {
            return (
              <Box
                key={key}
                padding=".8rem .55rem"
                maxWidth="33%"
                width={`${itemWidthPercent}%`}
                noFlexShrink
                tag="li"
              >
                <HorizontalItem {...item} withHoverOpacityFrom={0.87} />
              </Box>
            );
          });
        }, [items])}
      />
    </div>
  );
});

const ItemListSmall = memo<
  Pick<HorizontalItemsSectionProps, 'items' | 'backgroundColor'>
>(({ items = [], backgroundColor }) => {
  const hasMoreThan2 = items.length > 2;

  return (
    <div
      style={{
        position: 'relative',
      }}
    >
      <HorizontalScroller
        withSnapping
        centerContent
        overflowStyle="inside"
        gradientColor={backgroundColor}
        contentStyle={{
          padding: '0 .7rem',
        }}
        renderContent={useCallback(
          ({ snapItemStyle }) => {
            return items.map(({ key, ...item }) => {
              return (
                <Box
                  key={key}
                  padding="0 .6rem"
                  // when there's more than 2
                  width={hasMoreThan2 ? '17rem' : '50%'}
                  style={snapItemStyle}
                >
                  <HorizontalItem {...item} />
                </Box>
              );
            });
          },
          [items]
        )}
      />
    </div>
  );
});

export default HorizontalItemsSection;
