/* eslint-disable @typescript-eslint/no-explicit-any */

import { cn } from '@/lib/utils';
import {
  CaretDoubleLeftIcon,
  CaretDoubleRightIcon,
  CaretDownIcon,
  CaretLeftIcon,
  CaretRightIcon,
  TableIcon,
} from '@phosphor-icons/react';
import {
  ColumnDef,
  OnChangeFn,
  SortingState,
  TableState,
  flexRender,
  getCoreRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';
import Pagination from 'rc-pagination';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import LoaderIcon from '../icons/loader-icon';
import { Button } from '../ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '../ui/dropdown-menu';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '../ui/table';

type Props = {
  data: any[];
  isLoading?: boolean;
  structure: ColumnDef<any>[];
  sorting?: SortingState;
  setSorting?: OnChangeFn<SortingState>;
  className?: string;
  onRefresh?: () => void;
  shadow?: boolean;
  border?: boolean;
  rounded?: boolean;
  pagination?: {
    currentPage: number;
    lastPage: number;
    from?: number | null;
    to?: number | null;
    total?: number;
    perPage?: number;
  };
  onPageChange?: (page: number) => void;
  onLimitChange?: (limit: number) => void;
  onRowClick?: (row: any) => void;
};

export default function DataTable({
  data,
  isLoading = false,
  structure,
  sorting,
  setSorting,
  className,
  onRefresh,
  shadow = true,
  border = false,
  rounded = false,
  pagination,
  onPageChange,
  onLimitChange = () => {},
  onRowClick,
}: Props) {
  const columns = useMemo<ColumnDef<any>[]>(() => structure, [structure]);
  const { t } = useTranslation();

  // eslint-disable-next-line react-hooks/incompatible-library
  const table = useReactTable({
    data: data || [],
    columns,
    state: {
      sorting,
      onRefresh,
    } as Partial<TableState & { onRefresh: () => void }> | undefined,
    onSortingChange: setSorting,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    debugTable: false,
  });

  if (isLoading) {
    return (
      <div
        className={`bg-white/5 p-10 ${border ? 'ring ring-black/10' : ''} ${shadow ? 'shadow-box' : ''} ${rounded ? 'rounded-xl' : 'rounded-b-xl'}`}
      >
        <div className="flex h-32 w-full items-center justify-center gap-2">
          <LoaderIcon />
          {t('Loading...')}
        </div>
      </div>
    );
  }

  if (!data?.length) {
    return (
      <div
        className={`bg-white/5 p-10 ${border ? 'ring ring-black/10' : ''} ${shadow ? 'shadow-box' : ''} ${rounded ? 'rounded-xl' : 'rounded-b-xl'}`}
      >
        <div className="flex h-32 w-full flex-col items-center justify-center gap-2">
          <div className="flex h-10 w-10 items-center justify-center rounded-full bg-secondary p-1 dark:bg-white/10">
            <TableIcon
              weight="duotone"
              size="24"
              className="text-foreground dark:text-white/60"
            />
          </div>
          <span>{t('No data available')}</span>
        </div>
      </div>
    );
  }

  return (
    <div
      className={cn(
        `relative w-full overflow-x-auto ${border ? 'ring ring-black/10' : ''} ${shadow ? 'shadow-box' : ''} ${rounded ? 'rounded-xl' : 'rounded-b-xl'}`,
        className,
      )}
    >
      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow
              key={headerGroup.id}
              className="border-none hover:bg-transparent"
            >
              {headerGroup.headers.map((header) => (
                <TableHead
                  key={header.id}
                  className={cn(
                    'px-0',
                    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                    // @ts-expect-error
                    header?.column?.columnDef?.meta?.className,
                  )}
                >
                  {header.isPlaceholder ? null : (
                    <Button
                      variant="ghostPrimary"
                      size="default"
                      className="flex h-10 w-full cursor-pointer items-center justify-start rounded-none border-b border-black/10 bg-table-header px-4! text-sm font-semibold text-foreground hover:bg-table-header"
                      {...{
                        onClick: header.column.getToggleSortingHandler(),
                      }}
                    >
                      {
                        flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        ) as string
                      }
                      {header.column.getCanSort() &&
                        ({
                          asc: (
                            <CaretDownIcon
                              size="16"
                              className="text-foreground"
                              transform="rotate(180)"
                            />
                          ),
                          desc: (
                            <CaretDownIcon
                              size="16"
                              className="text-foreground"
                            />
                          ),
                        }[header.column.getIsSorted() as string] ?? (
                          <CaretDownIcon
                            size="16"
                            className="text-transparent"
                          />
                        ))}
                    </Button>
                  )}
                </TableHead>
              ))}
            </TableRow>
          ))}
        </TableHeader>
        <TableBody>
          {table.getRowModel().rows.map((row) => (
            <TableRow
              key={row.id}
              className={cn(
                'h-14 border-b border-white/6 odd:bg-table-odd even:bg-table-even odd:hover:bg-table-odd even:hover:bg-table-even dark:border-white/6',
                onRowClick ? 'cursor-pointer' : 'cursor-default',
              )}
              onClick={onRowClick ? () => onRowClick(row.original) : undefined}
            >
              {row.getVisibleCells().map((cell) => (
                <TableCell className="px-4 py-0" key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </TableCell>
              ))}
            </TableRow>
          ))}
        </TableBody>
      </Table>

      {onPageChange && pagination ? (
        <div className="flex items-center justify-between bg-white/5 p-2 md:px-4 md:py-3">
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button
                variant="outline"
                className="w-20 justify-between capitalize md:w-32"
              >
                {pagination?.perPage || 15}
                <CaretDownIcon weight="bold" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent>
              {[15, 30, 50, 100, 250].map((opt) => (
                <DropdownMenuItem key={opt} onClick={() => onLimitChange(opt)}>
                  {opt}
                </DropdownMenuItem>
              ))}
            </DropdownMenuContent>
          </DropdownMenu>
          <Pagination
            current={pagination.currentPage}
            total={pagination.total ?? 0}
            pageSize={pagination.perPage ?? 15}
            onChange={onPageChange}
            showTotal={() =>
              t(`Showing {{start}}-{{end}} of {{total}}`, {
                start: pagination.from || 0,
                end: pagination.to || 0,
                total: pagination.total || 0,
              })
            }
            showLessItems
            showSizeChanger={false}
            prevIcon={<CaretLeftIcon weight="bold" className="size-4" />}
            nextIcon={<CaretRightIcon weight="bold" className="size-4" />}
            jumpPrevIcon={
              <CaretDoubleLeftIcon weight="bold" className="size-4" />
            }
            jumpNextIcon={
              <CaretDoubleRightIcon weight="bold" className="size-4" />
            }
            className="rc-pagination-custom"
          />
        </div>
      ) : null}
    </div>
  );
}
