import { cn } from '@lib/utils';
import { m } from '@paraglide/messages';
import {
  type ColumnDef,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { Card, CardContent } from '@ui/card';
import { Item, ItemContent, ItemDescription, ItemTitle } from '@ui/item';
import { Label } from '@ui/label';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@ui/select';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@ui/table';
import Pagination from './Pagination';

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
  page: number;
  setPage: (page: number) => void;
  limit: number;
  setLimit: (page: number) => void;
  pagination: {
    currentPage: number;
    totalPage: number;
    totalItem: number;
  };
}

const DataTable = <TData, TValue>({
  columns,
  data,
  page,
  setPage,
  limit,
  setLimit,
  pagination,
}: DataTableProps<TData, TValue>) => {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <>
      <div className="overflow-hidden rounded-md border hidden lg:block">
        <Table className="bg-white">
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map((header) => {
                  return (
                    <TableHead
                      key={header.id}
                      colSpan={header.colSpan}
                      className={cn(
                        'px-4 bg-primary text-white text-sm',
                        header.column.columnDef.meta?.thClass,
                      )}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext(),
                          )}
                    </TableHead>
                  );
                })}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody className="**:data-[slot=table-cell]:first:w-8">
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && 'selected'}
                >
                  {row.getVisibleCells().map((cell) => (
                    <TableCell key={cell.id} className="px-4">
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell
                  colSpan={columns.length}
                  className="h-24 text-center"
                >
                  No results.
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:hidden">
        {table.getRowModel().rows?.length ? (
          table.getRowModel().rows.map((row) => (
            <Card key={row.id}>
              <CardContent>
                {row.getVisibleCells().map((cell) =>
                  cell.column.columnDef.id === 'actions' ? (
                    <Item
                      key={cell.id}
                      className="-m-4 w-[calc(100%+var(--spacing)*8)] bg-gray-50 rounded-t-none mt-1"
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </Item>
                  ) : (
                    <Item key={cell.id} className="px-0">
                      <ItemContent>
                        <ItemTitle>
                          {cell.column.columnDef.meta?.mLabel || 'No Label'}:
                        </ItemTitle>
                        <ItemDescription>
                          {flexRender(
                            cell.column.columnDef.cell,
                            cell.getContext(),
                          )}
                        </ItemDescription>
                      </ItemContent>
                    </Item>
                  ),
                )}
              </CardContent>
            </Card>
          ))
        ) : (
          <>No results.</>
        )}
      </div>
      <div className="flex items-center justify-between gap-2">
        <div className="hidden text-sm gap-2 lg:flex">
          <span>
            {m.common_page_show({
              count: pagination.totalItem,
              start: (pagination.currentPage - 1) * 10 + 1,
              end: Math.min(pagination.currentPage * 10, pagination.totalItem),
            })}
          </span>
        </div>
        <div className="flex max-w-full items-center gap-2 justify-between w-full lg:w-fit lg:gap-8">
          <div className="items-center gap-2 flex">
            <Label
              htmlFor="rows-per-page"
              className="hidden text-sm font-medium lg:block"
            >
              {m.common_per_page()}
            </Label>
            <Select
              value={`${limit}`}
              onValueChange={(value) => {
                setLimit(+value);
                setPage(1);
              }}
            >
              <SelectTrigger
                type="button"
                size="sm"
                className="w-30"
                id="rows-per-page"
              >
                <SelectValue placeholder={m.common_select_page_size()} />
              </SelectTrigger>
              <SelectContent side="top">
                {[10, 30, 50, 100].map((pageSize) => (
                  <SelectItem key={pageSize} value={`${pageSize}`}>
                    {pageSize}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <Pagination
            currentPage={page}
            totalPages={pagination.totalPage}
            onPageChange={(newPage) => setPage(newPage)}
          />
        </div>
      </div>
    </>
  );
};

export default DataTable;
