import { withSchema } from '@websolutespa/bom-core';
import { useCurrentState, useLabel } from '@websolutespa/bom-mixer-hooks';
import React, { useEffect, useMemo } from 'react';
import styled from 'styled-components';
import { UIStyledComponentProps } from '../../components/types';
import { getCssResponsive } from '../../components/utils';
import { pickChild } from '../utils';
import { PaginationConfig, PaginationContext, PaginationUpdateType } from './pagination-context';
import { PaginationNext } from './pagination-next';
import { PaginationPages } from './pagination-pages';
import { PaginationPrevious } from './pagination-previous';

type Props = {
  className?: string;
  count?: number;
  initialPage?: number;
  limit?: number;
  page?: number;
  onChange?: (val: number) => void;
  urlResolver?: (page: number) => string;
};

export type PaginationProps = UIStyledComponentProps<Props>;

const StyledPagination = styled.div`
  --pagination-size: 2rem;
  display: flex;
  justify-content: center;
  ${props => getCssResponsive(props)}
`;

const StyledNav = styled.ul`
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-variant: tabular-nums;
  font-feature-settings: 'tnum';
  font-size: 0.875rem;

  &>li {
    padding: 0;
  }

  :global(button:last-of-type) {
    margin-right: 0;
  }
`;

function PaginationBase({
  className = '',
  initialPage = 1,
  count = 1,
  limit = 7,
  page: customPage,
  children,
  onChange,
  urlResolver,
  ...props
}: React.PropsWithChildren<PaginationProps>) {
  const label = useLabel();

  const [page, setPage, pageRef] = useCurrentState(initialPage);

  const [prevChildren] = pickChild(PaginationPrevious, children);
  const [nextChildren] = pickChild(PaginationNext, children);

  const [prevItem, nextItem] = useMemo(() => {
    const hasChildren = (c: any) => React.Children.count(c) > 0;
    const prevDefault = <PaginationPrevious>prev</PaginationPrevious>;
    const nextDefault = <PaginationNext>next</PaginationNext>;
    return [
      hasChildren(prevChildren) ? prevChildren : prevDefault,
      hasChildren(nextChildren) ? nextChildren : nextDefault,
    ];
  }, [prevChildren, nextChildren]);

  const update = (type: PaginationUpdateType) => {
    if (type === 'prev' && pageRef.current > 1) {
      setPage(last => last - 1);
    }
    if (type === 'next' && pageRef.current < count) {
      setPage(last => last + 1);
    }
  };
  const values = useMemo<PaginationConfig>(() => {
    return {
      currentPage: page,
      isFirst: page <= 1,
      isLast: page >= count,
      update,
      resolveUrl: (page: number) => (urlResolver ? urlResolver(page) : undefined),
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [page, count]);

  useEffect(() => {
    onChange && onChange(page);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [page]);

  useEffect(() => {
    if (customPage !== undefined) {
      setPage(customPage);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [customPage]);

  return (
    <PaginationContext.Provider value={values}>
      <StyledPagination
        className={className} {...props}
        as="nav" role="navigation" aria-label={label('landmark.pagination')}
      >
        <StyledNav>
          {prevItem}
          <PaginationPages count={count} current={page} limit={limit} setPage={setPage} />
          {nextItem}
        </StyledNav>
      </StyledPagination>
    </PaginationContext.Provider>
  );
}

export const Pagination = withSchema(
  PaginationBase,
  {
    Previous: PaginationPrevious,
    Next: PaginationNext,
  });
