import { ColumnDef, Table as ReactTable, Row, flexRender } from "@tanstack/react-table";
import { PropsWithChildren, ReactNode } from "react";

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
  Separator,
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/ui";

import { cn } from "@/lib/utils";
import { DataTableColumnHeader } from "./DataTableColumnHeader";
import { DataTablePagination, DataTablePaginationProps } from "./DataTablePagination";

export type DataTableColumnProps<TData, TValue> = ColumnDef<TData, TValue>;

export type DataTablePaginationOptionsProps<TData> = Pick<
  DataTablePaginationProps<TData>,
  "visible" | "enablePageSizeSelector"
>;

export type DataTableHeaderOptionsProps = {
  visible: boolean;
};

export type DataTableProps<TData> = PropsWithChildren<{
  table: ReactTable<TData>;
  title?: ReactNode;
  description?: ReactNode;
  caption?: ReactNode;
  paginationOptions?: DataTablePaginationOptionsProps<TData>;
  headerOptions?: DataTableHeaderOptionsProps;
  className?: string;
  contentClassName?: string;
  footerClassName?: string;
  rowClassName?: string;
  cellClassName?: string;
  onRowClick?: (row: Row<TData>) => void;
  activeRowIndex?: number;
}>;

export function DataTable<TData>({
  table,
  title,
  description,
  caption,
  paginationOptions,
  headerOptions = { visible: true },
  children,
  className,
  contentClassName,
  footerClassName,
  rowClassName,
  cellClassName,
  onRowClick,
  activeRowIndex,
}: DataTableProps<TData>) {
  const headerVisible = headerOptions?.visible;

  return (
    <Card className={className}>
      {(title || description) && (
        <CardHeader className='pb-0'>
          <CardTitle>{title}</CardTitle>
          <CardDescription>{description}</CardDescription>
        </CardHeader>
      )}
      <CardContent className={cn("pt-6", contentClassName)}>
        {children && (
          <>
            <div className='flex space-x-2'>{children}</div>
            <Separator className='my-4' />
          </>
        )}

        <Table>
          {typeof caption !== "undefined" && <TableCaption>{caption}</TableCaption>}
          {headerVisible && table.getHeaderGroups().length && (
            <TableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id} className={rowClassName}>
                  {headerGroup.headers.map((header) => (
                    <TableHead
                      key={header.id}
                      colSpan={header.colSpan}
                      style={{
                        width:
                          header.getSize() === Number.MAX_SAFE_INTEGER ? "auto" : header.getSize(),
                      }}
                    >
                      <DataTableColumnHeader table={table} header={header} />
                    </TableHead>
                  ))}
                </TableRow>
              ))}
            </TableHeader>
          )}
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  onClick={() => {
                    if (onRowClick) {
                      onRowClick(row);
                    }
                  }}
                  tabIndex={0}
                  key={row.id}
                  data-state={row.getIsSelected() && "selected"}
                  className={cn(
                    row.getIsSelected() || activeRowIndex === row.index
                      ? "bg-accent cursor-pointer hover:bg-accent"
                      : "cursor-pointer",
                    rowClassName
                  )}
                >
                  {row.getVisibleCells().map((cell) => (
                    <TableCell
                      key={cell.id}
                      className={cellClassName}
                      style={{
                        width:
                          cell.column.getSize() === Number.MAX_SAFE_INTEGER
                            ? "auto"
                            : cell.column.getSize(),
                      }}
                    >
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow className={rowClassName}>
                <TableCell
                  className={cn("h-24 text-center", cellClassName)}
                  colSpan={table.getAllColumns.length}
                >
                  No hay datos para mostrar
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </CardContent>
      <CardFooter className={footerClassName}>
        <DataTablePagination className='flex-1' table={table} {...paginationOptions} />
      </CardFooter>
    </Card>
  );
}
