/*
 * Copyright (c) DD360 and its affiliates.
 */

import { SetStateAction, useCallback, useMemo, useState } from 'react'
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/outline'
import { composeClasses } from 'lib/classes'
import Text from '../Typography'

type Pages =
  | '5'
  | '10'
  | '15'
  | '20'
  | '25'
  | '30'
  | '35'
  | '40'
  | '45'
  | '50'
  | '55'
  | '60'
  | '65'
  | '70'
  | '75'
  | '80'
  | '85'
  | '90'
  | '95'
  | '100'
  | '105'

export interface PaginationProps {
  totalPages: number
  currentPage: number
  sliceSize?: Pages
  totalRows?: number
  firstText?: string
  secondText?: string
  goToPreviousPage: () => void
  goToNextPage: () => void
  goToPage: (page: number) => void
  setSize: React.Dispatch<SetStateAction<number>>
}

const buttonStyle =
  'w-full h-full flex justify-center items-center rounded-full hover:bg-gray-200'

const Pagination = ({
  totalPages,
  totalRows,
  currentPage,
  sliceSize = '5',
  firstText,
  secondText,
  goToPreviousPage,
  goToNextPage,
  goToPage,
  setSize
}: PaginationProps) => {
  const [selectSliceSize, setSelectSliceSize] = useState(sliceSize)
  const totalItems = useMemo(() => {
    if (totalRows) return totalRows
    return totalPages * Number(sliceSize)
  }, [totalRows, totalPages, sliceSize])

  const pages = useMemo(() => {
    const pagesList = new Array(totalPages).fill(0).map((_, index) => index + 1)

    if (totalPages > 5 && currentPage <= 5) return pagesList.slice(0, 5)
    if (totalPages > 5 && currentPage + 5 > totalPages)
      return pagesList.slice(totalPages - 5, totalPages)
    if (totalPages > 5 && currentPage > 5)
      return pagesList.slice(currentPage - 3, currentPage + 2)

    return pagesList
  }, [totalPages, currentPage, selectSliceSize])

  const options = useMemo(() => {
    const optionList = []
    for (let i = 5; i <= totalItems; i += 5) {
      optionList.push(i)
    }

    // make sure the last value is in the option list
    if (optionList[optionList.length - 1] !== totalItems) {
      optionList.push(totalItems)
    }

    return optionList
  }, [totalItems])

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLSelectElement>) => {
      setSize(Number(e.target.value))
      setSelectSliceSize(e.target.value as Pages)
    },
    []
  )

  if (totalPages === 0) {
    return <></>
  }

  return (
    <div
      role="pagination"
      className="flex flex-col md:flex-row items-center md:gap-6"
    >
      <div className="flex items-center">
        {firstText && <Text size="base">{firstText}</Text>}

        <select
          role="select-slice-size"
          name="custom-pagination"
          value={totalItems <= Number(sliceSize) ? totalItems : selectSliceSize}
          className="w-auto pl-2 mr-2 outline-none text-primary bg-transparent"
          onChange={(e) => handleChange(e)}
        >
          {options.map((opt) => {
            return (
              <option role="option" key={opt} value={opt}>
                {opt}
              </option>
            )
          })}
        </select>
        {secondText && <Text size="base">{secondText}</Text>}
      </div>
      <div className="flex items-center">
        <ul className="flex h-6">
          <li className="w-6 h-6">
            <button
              className={buttonStyle}
              onClick={goToPreviousPage}
              disabled={currentPage <= 1}
            >
              <ChevronLeftIcon className="w-4" />
            </button>
          </li>
          {currentPage > 5 && (
            <>
              <li className="w-6 h-6">
                <button
                  role="first-page"
                  className={buttonStyle}
                  onClick={() => goToPage(1)}
                >
                  <Text variant="small">1</Text>
                </button>
              </li>
              <li className="w-6 h-6">
                <div className="w-full h-full text-center select-none">
                  <Text variant="small">...</Text>
                </div>
              </li>
            </>
          )}
          {pages.map((page) => (
            <li key={`${page}-page`} className="w-6 h-6" role="list-page">
              <button
                className={composeClasses(
                  buttonStyle,
                  page === currentPage &&
                    'bg-primary text-white hover:bg-primary'
                )}
                onClick={() => goToPage(page)}
              >
                <Text variant="small">{page}</Text>
              </button>
            </li>
          ))}
          {totalPages > 5 &&
            (currentPage <= 5 || currentPage <= totalPages - 5) && (
              <>
                <li className="w-6 h-6">
                  <div className="w-full h-full text-center select-none">
                    <Text variant="small">...</Text>
                  </div>
                </li>
                <li className="w-6 h-6">
                  <button
                    role="last-page"
                    className={buttonStyle}
                    onClick={() => goToPage(totalPages)}
                  >
                    <Text variant="small">{totalPages}</Text>
                  </button>
                </li>
              </>
            )}
          <li className="w-6 h-6">
            <button
              className={buttonStyle}
              onClick={goToNextPage}
              disabled={currentPage >= totalPages}
            >
              <ChevronRightIcon className="w-4" />
            </button>
          </li>
        </ul>
      </div>
    </div>
  )
}

Pagination.displayName = 'Pagination'

export default Pagination
