"use client"

/* eslint-disable @typescript-eslint/no-explicit-any */
import {
  type ColumnDef,
  type PaginationState,
  flexRender,
  getCoreRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from "@tanstack/react-table"
import { ChevronLeft, ChevronRight } from "lucide-react"
import { useEffect, useMemo, useState } from "react"

type ResponsiveDataTableProps<T> = {
  columns: ColumnDef<T, any>[]
  data: T[]
  rowKey: (row: T) => string
  renderActions?: (row: T) => React.ReactNode
  emptyMessage?: string
  totalPages?: number
  totalItems?: number
  pageSize?: number
  onPageChange?: (page: number) => void
}

export function ResponsiveDataTable<T>({
  columns,
  data,
  rowKey,
  renderActions,
  emptyMessage = "Aucune donnée à afficher.",
  totalPages,
  totalItems,
  pageSize: controlledPageSize = 10,
  onPageChange: onExternalPageChange,
}: ResponsiveDataTableProps<T>) {
  const isBackendPagination = totalPages !== undefined || totalItems !== undefined

  const [paginationState, setPaginationState] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: controlledPageSize,
  })

  useEffect(() => {
    if (controlledPageSize !== undefined && paginationState.pageSize !== controlledPageSize) {
      setPaginationState((prev) => ({ ...prev, pageSize: controlledPageSize }))
    }
  }, [controlledPageSize, paginationState.pageSize])

  const pagination = useMemo(
    () => ({
      pageIndex: paginationState.pageIndex,
      pageSize: controlledPageSize ?? paginationState.pageSize,
    }),
    [paginationState.pageIndex, paginationState.pageSize, controlledPageSize],
  )

  // eslint-disable-next-line react-hooks/incompatible-library
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    state: { pagination },
    manualPagination: isBackendPagination,
    pageCount: isBackendPagination ? totalPages : undefined,
    onPaginationChange: (updater) => {
      const next = typeof updater === "function" ? updater(pagination) : updater
      setPaginationState(next)
      if (onExternalPageChange) onExternalPageChange(next.pageIndex + 1)
    },
    ...(isBackendPagination ? {} : { getPaginationRowModel: getPaginationRowModel() }),
  })

  const totalCount = isBackendPagination ? (totalItems ?? 0) : data.length
  const showPagination = totalCount > controlledPageSize
  const pageCount = isBackendPagination ? totalPages ?? 0 : table.getPageCount()
  const currentPage = table.getState().pagination.pageIndex + 1

  return (
    <div className="flex flex-col gap-0 rounded-xl border border-gray-200 bg-white overflow-hidden">
      <div className="overflow-x-auto">
        <table className="w-full text-sm">
          <thead>
            {table.getHeaderGroups().map((headerGroup) => (
              <tr key={headerGroup.id} className="border-b border-gray-200 bg-gray-50">
                {headerGroup.headers.map((header) => (
                  <th
                    key={header.id}
                    className="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wide whitespace-nowrap"
                  >
                    {flexRender(header.column.columnDef.header, header.getContext())}
                  </th>
                ))}
                {renderActions && (
                  <th className="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wide whitespace-nowrap">
                    Actions
                  </th>
                )}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.length > 0 ? (
              table.getRowModel().rows.map((row) => {
                const rowId = rowKey(row.original)
                return (
                  <tr
                    key={rowId}
                    className="border-b border-gray-100 last:border-0 hover:bg-gray-50/60 transition-colors"
                  >
                    {row.getVisibleCells().map((cell) => (
                      <td key={cell.id} className="px-4 py-3 align-middle whitespace-nowrap">
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </td>
                    ))}
                    {renderActions && (
                      <td className="px-4 py-3 align-middle whitespace-nowrap">
                        {renderActions(row.original)}
                      </td>
                    )}
                  </tr>
                )
              })
            ) : (
              <tr>
                <td
                  colSpan={columns.length + (renderActions ? 1 : 0)}
                  className="px-4 py-12 text-center text-sm text-gray-400"
                >
                  {emptyMessage}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {showPagination && (
        <div className="flex items-center justify-between px-4 py-3 border-t border-gray-100 bg-white">
          <p className="text-xs text-gray-500">
            Page <span className="font-medium text-gray-700">{currentPage}</span> sur{" "}
            <span className="font-medium text-gray-700">{pageCount}</span>
          </p>
          <div className="flex items-center gap-1.5">
            {Array.from({ length: pageCount }, (_, i) => i + 1)
              .filter((p) => {
                if (pageCount <= 7) return true
                if (p === 1 || p === pageCount) return true
                if (Math.abs(p - currentPage) <= 1) return true
                return false
              })
              .reduce<(number | "...")[]>((acc, p, idx, arr) => {
                if (idx > 0 && typeof arr[idx - 1] === "number" && (p as number) - (arr[idx - 1] as number) > 1) {
                  acc.push("...")
                }
                acc.push(p)
                return acc
              }, [])
              .map((item, idx) =>
                item === "..." ? (
                  <span key={`ellipsis-${idx}`} className="px-1 text-xs text-gray-400">
                    …
                  </span>
                ) : (
                  <button
                    key={item}
                    onClick={() => {
                      const newIndex = (item as number) - 1
                      setPaginationState((prev) => ({ ...prev, pageIndex: newIndex }))
                      if (onExternalPageChange) onExternalPageChange(item as number)
                    }}
                    className={`h-7 min-w-7 px-2 rounded text-xs font-medium transition-colors ${
                      item === currentPage
                        ? "bg-[#9c773a] text-white"
                        : "text-gray-600 hover:bg-gray-100"
                    }`}
                  >
                    {item}
                  </button>
                ),
              )}
            <button
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
              className="h-7 w-7 flex items-center justify-center rounded border border-gray-200 text-gray-500 hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
            >
              <ChevronLeft className="size-3.5" />
            </button>
            <button
              onClick={() => table.nextPage()}
              disabled={!table.getCanNextPage()}
              className="h-7 w-7 flex items-center justify-center rounded border border-gray-200 text-gray-500 hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
            >
              <ChevronRight className="size-3.5" />
            </button>
          </div>
        </div>
      )}
    </div>
  )
}
