import { useMemo } from 'react';

import { useTranslation } from '../../core/hooks/useTranslation';
import { useTestIdAttribute } from '../../hooks/useTestIdAttribute';
import { CommonProps } from '../../types';
import { assertEmptyObject } from '../../utils/assertEmptyObject';
import { makeTestId } from '../../utils/makeTestId';
import { IconGlyph } from '../Icon/constants';

import { PaginationArrow } from './components/PaginationArrow/PaginationArrow';
import {
  StyledPaginationList,
  StyledPaginationListItem,
  StyledPaginationNav,
  TunedMoreIcon,
  TunedPageLink,
} from './styled';
import { Pages, PaginationSpecialPages, getRanges } from './utils/getRanges';

/** Props for the {@link Pagination} component */
export interface PaginationProps extends CommonProps {
  /** Current active page starts from 0 */
  currentPage: number;
  /** Total pages */
  totalPages: number;
  /** Function that used for build page links to params */
  linkToBuilder: (pageNumber: number) => string;
}

/**
 * Pagination component.
 *
 * ```tsx
 * import { Pagination } from 'ui-kit';
 *
 * <Pagination currentPage={0} totalPages={40} linkToBuilder={(pageNumber) => `/?page=${pageNumber}`} />
 * ```
 */
export function Pagination(props: PaginationProps) {
  const { currentPage, totalPages, linkToBuilder, className, testId, ariaDescribedBy, ...rest } = props;
  assertEmptyObject(rest);

  const { t } = useTranslation();
  const testIdAttribute = useTestIdAttribute();

  const renderPage = (page: Pages) => {
    switch (page) {
      case PaginationSpecialPages.MorePagesLeft:
      case PaginationSpecialPages.MorePagesRight:
        return <TunedMoreIcon glyph={IconGlyph.More} testId={makeTestId(testId, 'more')} />;

      case currentPage:
        return (
          <TunedPageLink
            ariaCurrent="page"
            ariaLabel={t('ui.pagination.currentPage', { page: page + 1 })}
            disabled
            testId={makeTestId(testId, 'page', page.toString())}
            to={linkToBuilder(page)}
          >
            {page + 1}
          </TunedPageLink>
        );

      default:
        return (
          <TunedPageLink
            ariaLabel={t('ui.pagination.goToPage', { page: page + 1 })}
            testId={makeTestId(testId, 'page', page.toString())}
            to={linkToBuilder(page)}
          >
            {page + 1}
          </TunedPageLink>
        );
    }
  };

  const ranges = useMemo(() => getRanges(currentPage, totalPages), [currentPage, totalPages]);

  return (
    <StyledPaginationNav
      aria-describedby={ariaDescribedBy}
      aria-label={t('ui.pagination.pagination')}
      className={className}
      role="navigation"
      {...{ [testIdAttribute]: testId }}
    >
      <StyledPaginationList {...{ [testIdAttribute]: makeTestId(testId, 'list') }}>
        <StyledPaginationListItem>
          <PaginationArrow
            ariaLabel={t('ui.pagination.goToPreviousPage')}
            disabled={currentPage <= 0}
            icon={IconGlyph.ChevronLeft}
            testId={makeTestId(testId, 'arrow-prev')}
            to={linkToBuilder(Math.max(currentPage - 1, 0))}
          />
        </StyledPaginationListItem>

        {ranges.map((page) => (
          <StyledPaginationListItem key={page}>{renderPage(page)}</StyledPaginationListItem>
        ))}

        <StyledPaginationListItem>
          <PaginationArrow
            ariaLabel={t('ui.pagination.goToNextPage')}
            disabled={totalPages === 0 || currentPage >= totalPages - 1}
            icon={IconGlyph.ChevronRight}
            testId={makeTestId(testId, 'arrow-next')}
            to={linkToBuilder(Math.min(currentPage + 1, totalPages - 1))}
          />
        </StyledPaginationListItem>
      </StyledPaginationList>
    </StyledPaginationNav>
  );
}
