"use client"

import {
  ChevronLeftIcon,
  ChevronRightIcon,
  MoreHorizontalIcon,
} from "lucide-react"
import type * as React from "react"
import { useEffect, useState } from "react"

import { cn } from "@/lib/utils"

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "./select"

export interface PaginationProps {
  page: number
  size: number
  total: number
  sizeOptions?: number[]
  onPageChange?: (page: number) => void
  onSizeChange?: (size: number) => void
  className?: string
}

function Pagination({
  page,
  size,
  total,
  sizeOptions = [10, 20, 50, 100],
  onPageChange,
  onSizeChange,
  className,
}: PaginationProps) {
  const [currentPage, setCurrentPage] = useState(page)
  const totalPages = Math.ceil(total / size)

  // 同步外部 page 变化
  useEffect(() => {
    setCurrentPage(page)
  }, [page])

  // 分页器逻辑
  const generatePaginationItems = () => {
    // 最多显示7个页码，其余用省略号
    const SIBLINGS = 1 // 当前页左右各显示的页码数
    const DOTS = -1 // 省略号标记

    if (totalPages <= 7) {
      // 总页数少于7，全部显示
      return Array.from({ length: totalPages }, (_, i) => i + 1)
    }

    // 是否需要显示左边的省略号
    const showLeftDots = currentPage > 2 + SIBLINGS

    // 是否需要显示右边的省略号
    const showRightDots = currentPage < totalPages - (2 + SIBLINGS)

    if (showLeftDots && showRightDots) {
      // 两边都有省略号
      const leftSiblingIndex = Math.max(currentPage - SIBLINGS, 1)
      const rightSiblingIndex = Math.min(currentPage + SIBLINGS, totalPages)

      return [
        1,
        DOTS,
        ...Array.from(
          { length: rightSiblingIndex - leftSiblingIndex + 1 },
          (_, i) => leftSiblingIndex + i,
        ),
        DOTS,
        totalPages,
      ]
    }

    if (!showLeftDots && showRightDots) {
      // 只有右边有省略号
      return [
        ...Array.from({ length: 3 + SIBLINGS * 2 }, (_, i) => i + 1),
        DOTS,
        totalPages,
      ]
    }

    if (showLeftDots && !showRightDots) {
      // 只有左边有省略号
      return [
        1,
        DOTS,
        ...Array.from(
          { length: 3 + SIBLINGS * 2 },
          (_, i) => totalPages - (3 + SIBLINGS * 2) + i + 1,
        ),
      ]
    }

    return []
  }

  const handlePageChange = (newPage: number) => {
    if (newPage < 1 || newPage > totalPages || newPage === currentPage) {
      return
    }
    setCurrentPage(newPage)
    onPageChange?.(newPage)
  }

  const handlePageSizeChange = (newSize: string) => {
    const parsedSize = parseInt(newSize, 10)
    if (onSizeChange) {
      onSizeChange(parsedSize)
    }
  }

  const paginationItems = generatePaginationItems()

  return (
    <div className={`flex flex-wrap items-center gap-4 ${className || ""}`}>
      <div className="flex-none flex items-center gap-2 text-sm text-muted-foreground">
        共 {total} 条记录，每页
        <Select value={size.toString()} onValueChange={handlePageSizeChange}>
          <SelectTrigger className="h-8 w-20">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {sizeOptions.map(option => (
              <SelectItem key={option} value={option.toString()}>
                {option}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
        条
      </div>

      <PaginationLayout>
        <PaginationContent>
          <PaginationItem>
            <PaginationPrevious
              onClick={() => handlePageChange(currentPage - 1)}
              className={
                currentPage === 1 ? "opacity-50 pointer-events-none" : ""
              }
            />
          </PaginationItem>

          {paginationItems.map((pageNum, index) => {
            if (pageNum === -1) {
              return (
                <PaginationItem key={`dots-${index}`}>
                  <PaginationEllipsis />
                </PaginationItem>
              )
            }

            return (
              <PaginationItem key={pageNum}>
                <PaginationLink
                  isActive={pageNum === currentPage}
                  onClick={() => handlePageChange(pageNum)}
                >
                  {pageNum}
                </PaginationLink>
              </PaginationItem>
            )
          })}

          <PaginationItem>
            <PaginationNext
              onClick={() => handlePageChange(currentPage + 1)}
              className={
                currentPage === totalPages
                  ? "opacity-50 pointer-events-none"
                  : ""
              }
            />
          </PaginationItem>
        </PaginationContent>
      </PaginationLayout>
    </div>
  )
}

function PaginationLayout({
  className,
  ...props
}: React.ComponentProps<"nav">) {
  return (
    <nav
      // role="navigation"
      aria-label="pagination"
      data-slot="pagination"
      className={cn("flex-none", className)}
      {...props}
    />
  )
}

function PaginationContent({
  className,
  ...props
}: React.ComponentProps<"ul">) {
  return (
    <ul
      data-slot="pagination-content"
      className={cn("flex flex-row items-center gap-1", className)}
      {...props}
    />
  )
}

function PaginationItem({ ...props }: React.ComponentProps<"li">) {
  return <li data-slot="pagination-item" {...props} />
}

type PaginationLinkProps = {
  isActive?: boolean
} & React.ComponentProps<"a">

function PaginationLink({
  className,
  isActive,
  ...props
}: PaginationLinkProps) {
  return (
    <a
      aria-current={isActive ? "page" : undefined}
      data-slot="pagination-link"
      data-active={isActive}
      className={cn(
        "inline-flex items-center justify-center text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-9 w-9 rounded-md border border-input hover:bg-secondary hover:text-secondary-foreground",
        `bg-card`,
        isActive &&
          "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground",
        className,
      )}
      {...props}
    />
  )
}

function PaginationPrevious({
  className,
  ...props
}: React.ComponentProps<typeof PaginationLink>) {
  return (
    <PaginationLink
      aria-label="Go to previous page"
      className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
      {...props}
    >
      <ChevronLeftIcon />
    </PaginationLink>
  )
}

function PaginationNext({
  className,
  ...props
}: React.ComponentProps<typeof PaginationLink>) {
  return (
    <PaginationLink
      aria-label="Go to next page"
      className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
      {...props}
    >
      <ChevronRightIcon />
    </PaginationLink>
  )
}

function PaginationEllipsis({
  className,
  ...props
}: React.ComponentProps<"span">) {
  return (
    <span
      aria-hidden
      data-slot="pagination-ellipsis"
      className={cn("flex size-9 items-center justify-center", className)}
      {...props}
    >
      <MoreHorizontalIcon className="size-4" />
      <span className="sr-only">More pages</span>
    </span>
  )
}

export {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLayout,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
}
