import { PaginationResult } from './types'
import {
  calculationPages,
  calculationStartPageAndEndPage,
  clampCurrentPage,
  DEFAULT_MAX_VISIBLE_PAGES,
  DEFAULT_PAGE_SIZE,
  filterPagination,
  getTotalItems,
  indiceCalculation,
  normalizePageSize,
} from './utils'

const pagination = <T>(
  items: T[] | null | undefined,
  currentPage = 1,
  pageSize: number = DEFAULT_PAGE_SIZE,
  maxVisiblePages: number = DEFAULT_MAX_VISIBLE_PAGES
): PaginationResult<T> => {
  const totalItems = getTotalItems(items)
  const safePageSize = normalizePageSize(pageSize)
  const safeMaxVisiblePages =
    Number.isFinite(maxVisiblePages) && maxVisiblePages > 0
      ? Math.floor(maxVisiblePages)
      : DEFAULT_MAX_VISIBLE_PAGES

  const { allPages } = calculationPages(totalItems, safePageSize)
  const verifyCurrentPage = clampCurrentPage(currentPage, allPages)

  const { startPage, endPage } = calculationStartPageAndEndPage(
    allPages,
    safeMaxVisiblePages,
    verifyCurrentPage
  )

  const { endIndex, pages, startIndex } = indiceCalculation(
    safePageSize,
    totalItems,
    verifyCurrentPage,
    startPage,
    endPage
  )

  const { contentItems } = filterPagination(
    items,
    safePageSize,
    verifyCurrentPage
  )

  return {
    AllItems: totalItems,
    currentPage: verifyCurrentPage,
    pageSize: safePageSize,
    allPages,
    startPage,
    endPage,
    startIndex,
    endIndex,
    pages,
    items: contentItems,
  }
}

export default pagination
export type { PaginationResult } from './types'
