import { useMemo } from "react"
import type { Table } from "@tanstack/react-table"

import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { cn } from "@/lib/utils"

type TablePaginationProps<TData> = {
  table: Table<TData>
  pageSizeOptions?: number[]
  rowsPerPageLabel?: string
  showSelectedRows?: boolean
  selectionLabel?: (selected: number, total: number) => React.ReactNode
  className?: string
}

function buildPaginationRange(currentPage: number, pageCount: number) {
  if (pageCount <= 7) {
    return Array.from({ length: pageCount }, (_, index) => index + 1)
  }

  const range: Array<number | "ellipsis-left" | "ellipsis-right"> = [1]
  const left = Math.max(2, currentPage - 1)
  const right = Math.min(pageCount - 1, currentPage + 1)

  if (left > 2) {
    range.push("ellipsis-left")
  }

  for (let page = left; page <= right; page += 1) {
    range.push(page)
  }

  if (right < pageCount - 1) {
    range.push("ellipsis-right")
  }

  range.push(pageCount)
  return range
}

export function TablePagination<TData>({
  table,
  pageSizeOptions = [10, 20, 30, 50],
  rowsPerPageLabel = "Itens por página",
  showSelectedRows = false,
  selectionLabel,
  className,
}: TablePaginationProps<TData>) {
  const pageIndex = table.getState().pagination.pageIndex
  const pageSize = table.getState().pagination.pageSize
  const pageCount = Math.max(table.getPageCount(), 1)
  const currentPage = Math.min(pageIndex + 1, pageCount)

  const totalRows = table.getFilteredRowModel().rows.length
  const currentRows = table.getRowModel().rows.length

  const rangeStart = totalRows === 0 ? 0 : pageIndex * pageSize + 1
  const rangeEnd = totalRows === 0 ? 0 : rangeStart + currentRows - 1

  const selectedCount = table.getFilteredSelectedRowModel().rows.length

  const paginationRange = useMemo(
    () => buildPaginationRange(currentPage, pageCount),
    [currentPage, pageCount]
  )

  const handlePageChange = (pageNumber: number) => {
    table.setPageIndex(pageNumber - 1)
  }

  return (
    <div
      className={cn(
        "flex flex-col gap-4 border-t border-slate-200 px-4 pt-4 text-sm text-neutral-600 md:flex-row md:items-center md:justify-between",
        className
      )}
    >
      {showSelectedRows ? (
        <div className="text-xs text-neutral-500 md:text-sm">
          {selectionLabel
            ? selectionLabel(selectedCount, totalRows)
            : `${selectedCount} de ${totalRows} selecionados`}
        </div>
      ) : (
        <div className="sr-only">Paginação de tabela</div>
      )}

      <div className="flex flex-col-reverse items-center gap-3 md:flex-row md:gap-4 md:justify-end md:flex-1">
        {pageSizeOptions.length > 0 ? (
          <div className="flex items-center gap-2 text-xs tracking-wide text-neutral-500 md:text-sm">
            <span>{rowsPerPageLabel}</span>
            <Select
              value={`${pageSize}`}
              onValueChange={(value) => {
                table.setPageSize(Number(value))
                table.setPageIndex(0)
              }}
            >
              <SelectTrigger className="h-8 w-20">
                <SelectValue placeholder={pageSize} />
              </SelectTrigger>
              <SelectContent align="end">
                {pageSizeOptions.map((option) => (
                  <SelectItem key={option} value={`${option}`}>
                    {option}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        ) : null}

        <div className="flex flex-col items-center gap-2 md:flex-row md:gap-3">
          <span className="text-xs font-medium text-neutral-500 md:text-sm">
            {totalRows === 0
              ? "Nenhum registro"
              : `Mostrando ${rangeStart}-${rangeEnd} de ${totalRows}`}
          </span>
          <Pagination>
            <PaginationContent>
              <PaginationItem>
                <PaginationPrevious
                  disabled={!table.getCanPreviousPage()}
                  onClick={() => table.previousPage()}
                />
              </PaginationItem>
              {paginationRange.map((item, index) => {
                if (typeof item === "number") {
                  return (
                    <PaginationItem key={`page-${item}`}>
                      <PaginationLink
                        href="#"
                        isActive={item === currentPage}
                        onClick={(event) => {
                          event.preventDefault()
                          handlePageChange(item)
                        }}
                      >
                        {item}
                      </PaginationLink>
                    </PaginationItem>
                  )
                }
                return (
                  <PaginationItem key={`ellipsis-${item}-${index}`}>
                    <PaginationEllipsis />
                  </PaginationItem>
                )
              })}
              <PaginationItem>
                <PaginationNext
                  disabled={!table.getCanNextPage()}
                  onClick={() => table.nextPage()}
                />
              </PaginationItem>
            </PaginationContent>
          </Pagination>
        </div>
      </div>
    </div>
  )
}
