'use client'

import * as React from 'react'
import Link from 'next/link'
import {
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
  type ColumnDef,
  type SortingState,
} from '@tanstack/react-table'
import { ArrowUpDown, Search } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge'
import { EmptyState } from '@/components/ui/empty-state'
import { cn } from '@/lib/utils/cn'

export interface DataTableColumn {
  key: string
  label: string
  sortable?: boolean
  badge?: boolean
  className?: string
}

interface DataTableProps<T extends Record<string, unknown>> {
  columns: DataTableColumn[]
  data: T[]
  searchPlaceholder?: string
  rowHref?: (row: T) => string
  emptyTitle?: string
  emptyDescription?: string
}

function renderValue(value: unknown, badge?: boolean) {
  if (value === null || value === undefined || value === '') return <span className="text-muted-foreground">N/A</span>
  if (typeof value === 'boolean') {
    return <Badge variant={value ? 'success' : 'secondary'}>{value ? 'Oui' : 'Non'}</Badge>
  }
  if (badge) {
    const text = String(value)
    const variant =
      ['active', 'approved', 'published', 'sent', 'fulfilled', 'resolved'].includes(text)
        ? 'success'
        : ['pending', 'draft', 'scheduled', 'invited'].includes(text)
          ? 'warning'
          : ['rejected', 'failed', 'suspended', 'archived', 'cancelled'].includes(text)
            ? 'destructive'
            : 'secondary'
    return <Badge variant={variant}>{text}</Badge>
  }
  return String(value)
}

export function DataTable<T extends Record<string, unknown>>({
  columns,
  data,
  searchPlaceholder = 'Rechercher...',
  rowHref,
  emptyTitle = 'Aucune donnee',
  emptyDescription = 'Les donnees apparaitront ici des que Supabase contient des lignes.',
}: DataTableProps<T>) {
  const [sorting, setSorting] = React.useState<SortingState>([])
  const [globalFilter, setGlobalFilter] = React.useState('')

  const tableColumns = React.useMemo<ColumnDef<T>[]>(
    () =>
      columns.map((column) => ({
        accessorKey: column.key,
        header: ({ column: tableColumn }) => {
          if (!column.sortable) return column.label
          return (
            <Button
              variant="ghost"
              size="sm"
              className="-ml-3 h-8"
              onClick={() => tableColumn.toggleSorting(tableColumn.getIsSorted() === 'asc')}
            >
              {column.label}
              <ArrowUpDown className="ml-2 h-3.5 w-3.5" />
            </Button>
          )
        },
        cell: ({ row }) => {
          const content = renderValue(row.getValue(column.key), column.badge)
          if (!rowHref) return <div className={column.className}>{content}</div>
          return (
            <Link href={rowHref(row.original)} className={cn('block hover:text-primary', column.className)}>
              {content}
            </Link>
          )
        },
      })),
    [columns, rowHref],
  )

  const table = useReactTable({
    data,
    columns: tableColumns,
    state: { sorting, globalFilter },
    onSortingChange: setSorting,
    onGlobalFilterChange: setGlobalFilter,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    initialState: { pagination: { pageSize: 12 } },
  })

  if (!data.length) {
    return <EmptyState title={emptyTitle} description={emptyDescription} />
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2 rounded-md border bg-card px-3">
        <Search className="h-4 w-4 text-muted-foreground" />
        <Input
          value={globalFilter}
          onChange={(event) => setGlobalFilter(event.target.value)}
          placeholder={searchPlaceholder}
          className="border-0 bg-transparent px-0 shadow-none focus-visible:ring-0"
        />
      </div>
      <div className="overflow-hidden rounded-lg border bg-card">
        <div className="overflow-x-auto">
          <table className="w-full min-w-[760px] text-sm">
            <thead className="bg-muted/70">
              {table.getHeaderGroups().map((headerGroup) => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <th key={header.id} className="px-4 py-3 text-left font-medium text-muted-foreground">
                      {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody>
              {table.getRowModel().rows.map((row) => (
                <tr key={row.id} className="border-t transition-colors hover:bg-muted/40">
                  {row.getVisibleCells().map((cell) => (
                    <td key={cell.id} className="px-4 py-3 align-middle">
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <div className="flex items-center justify-between gap-3">
        <p className="text-sm text-muted-foreground">
          {table.getFilteredRowModel().rows.length} resultat(s), page {table.getState().pagination.pageIndex + 1} /{' '}
          {Math.max(table.getPageCount(), 1)}
        </p>
        <div className="flex gap-2">
          <Button variant="outline" size="sm" onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
            Precedent
          </Button>
          <Button variant="outline" size="sm" onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
            Suivant
          </Button>
        </div>
      </div>
    </div>
  )
}
