import {
  type CellContext,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  type HeaderContext,
  useReactTable,
  type ColumnDef,
  type FilterFn,
  type PaginationState,
  type RowSelectionState,
  type SortingState
} from "@tanstack/react-table";
import {
  forwardRef,
  useEffect,
  useState,
  type ComponentPropsWithoutRef,
  type CSSProperties,
  type ForwardedRef,
  type JSX,
  type ReactNode
} from "react";

import { Button } from "./button";
import { Checkbox } from "./checkbox";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger
} from "./dropdown-menu";
import {
  EmptyState,
  EmptyStateActions,
  EmptyStateDescription,
  EmptyStateHeader,
  EmptyStateTitle
} from "./empty-state";
import { Input, type InputProps } from "./input";
import { InputGroup, InputGroupPrefix } from "./input-group";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle
} from "./sheet";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
import { Skeleton } from "./skeleton";
import { Spinner } from "./spinner";
import { cn } from "../lib/cn";
import type { VariantProps } from "../lib/cva";
import { createDataAttributes, createSlot } from "../lib/contracts";
import {
  SortAscendingIcon,
  SortDescendingIcon,
  SortUnsortedIcon
} from "../lib/icons";
import {
  dataTableBodyVariants,
  dataTableCellVariants,
  dataTableContentVariants,
  dataTableHeaderCellVariants,
  dataTableHeaderVariants,
  dataTablePaginationVariants,
  dataTableRootVariants,
  dataTableRowVariants,
  dataTableSearchContainerVariants,
  dataTableSelectionBarVariants,
  dataTableStatusVariants,
  dataTableTableVariants,
  dataTableToolbarVariants
} from "./data-table.variants";

export type DataTableAlignment = "start" | "center" | "end";
export type DataTableDensity = "comfortable" | "compact";

export type DataTableSort = {
  desc?: boolean;
  id: string;
};

export type DataTableColumnContext<TData> = {
  column: DataTableColumn<TData>;
  sorted: "asc" | "desc" | false;
};

export type DataTableColumn<TData> = {
  accessor?: keyof TData | ((row: TData) => unknown);
  align?: DataTableAlignment;
  cell?: (row: TData) => ReactNode;
  header: ReactNode | ((column: DataTableColumnContext<TData>) => ReactNode);
  hideable?: boolean;
  id: string;
  searchValue?: (row: TData) => string;
  searchable?: boolean;
  sortable?: boolean;
  width?: number | string;
};

export type DataTableProps<TData> = Omit<ComponentPropsWithoutRef<"div">, "children"> & {
  columns: DataTableColumn<TData>[];
  defaultDensity?: DataTableDensity;
  defaultPageIndex?: number;
  defaultPageSize?: number;
  defaultSearchValue?: string;
  defaultSelection?: Record<string, boolean>;
  defaultSorting?: DataTableSort[];
  defaultVisibleColumns?: Record<string, boolean>;
  density?: DataTableDensity;
  empty?: ReactNode;
  enableSelection?: boolean;
  getRowId?: (row: TData, index: number) => string;
  loading?: boolean;
  loadingRowCount?: number;
  onDensityChange?: (density: DataTableDensity) => void;
  onPageIndexChange?: (pageIndex: number) => void;
  onPageSizeChange?: (pageSize: number) => void;
  onSearchValueChange?: (searchValue: string) => void;
  onSelectionChange?: (selection: Record<string, boolean>) => void;
  onSortingChange?: (sorting: DataTableSort[]) => void;
  onVisibleColumnsChange?: (visibility: Record<string, boolean>) => void;
  pageIndex?: number;
  pageSize?: number;
  pageSizeOptions?: number[];
  renderRowDetails?: (row: TData) => ReactNode;
  renderRowActions?: (row: TData) => ReactNode;
  rowDetailsDescription?: ReactNode | ((row: TData) => ReactNode);
  rowDetailsLabel?: string;
  rowDetailsTitle?: ReactNode | ((row: TData) => ReactNode);
  rows: TData[];
  searchLabel?: string;
  searchPlaceholder?: string;
  searchValue?: string;
  selection?: Record<string, boolean>;
  selectionLabel?: ReactNode | ((rows: TData[]) => ReactNode);
  selectionActions?: (rows: TData[]) => ReactNode;
  sorting?: DataTableSort[];
  tableLabel?: string;
  toolbarActions?: ReactNode;
  visibleColumns?: Record<string, boolean>;
};

type InternalColumnMeta<TData> = {
  align: DataTableAlignment;
  sourceColumn?: DataTableColumn<TData>;
  width?: number | string;
};

function useControllableState<T>({
  controlledValue,
  defaultValue,
  onChange
}: {
  controlledValue: T | undefined;
  defaultValue: T;
  onChange?: (value: T) => void;
}) {
  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
  const value = controlledValue ?? uncontrolledValue;

  const setValue = (nextValue: T | ((currentValue: T) => T)) => {
    const resolvedValue =
      typeof nextValue === "function"
        ? (nextValue as (currentValue: T) => T)(value)
        : nextValue;

    if (controlledValue === undefined) {
      setUncontrolledValue(resolvedValue);
    }

    onChange?.(resolvedValue);
  };

  return [value, setValue] as const;
}

function stringifySearchValue(value: unknown): string {
  if (value === null || value === undefined) {
    return "";
  }

  if (Array.isArray(value)) {
    return value.map((item) => stringifySearchValue(item)).join(" ");
  }

  if (value instanceof Date) {
    return value.toISOString();
  }

  if (typeof value === "object") {
    return Object.values(value as Record<string, unknown>)
      .map((item) => stringifySearchValue(item))
      .join(" ");
  }

  return String(value);
}

function getColumnAccessorValue<TData>(row: TData, column: DataTableColumn<TData>) {
  if (typeof column.accessor === "function") {
    return column.accessor(row);
  }

  if (typeof column.accessor === "string") {
    return row[column.accessor];
  }

  return undefined;
}

function getColumnSearchText<TData>(row: TData, column: DataTableColumn<TData>) {
  if (column.searchValue) {
    return column.searchValue(row);
  }

  return stringifySearchValue(getColumnAccessorValue(row, column));
}

function getColumnWidthStyle(width?: number | string): CSSProperties | undefined {
  if (width === undefined) {
    return undefined;
  }

  return {
    width: typeof width === "number" ? `${width}px` : width
  };
}

function getHeaderLabel<TData>(column: DataTableColumn<TData>) {
  return typeof column.header === "string" ? column.header : column.id;
}

function DataTableInner<TData>(
  {
    className,
    columns,
    defaultDensity = "comfortable",
    defaultPageIndex = 0,
    defaultPageSize = 5,
    defaultSearchValue = "",
    defaultSelection = {},
    defaultSorting = [],
    defaultVisibleColumns = {},
    density,
    empty,
    enableSelection = false,
    getRowId,
    loading = false,
    loadingRowCount = 5,
    onDensityChange,
    onPageIndexChange,
    onPageSizeChange,
    onSearchValueChange,
    onSelectionChange,
    onSortingChange,
    onVisibleColumnsChange,
    pageIndex,
    pageSize,
    pageSizeOptions = [5, 10, 20],
    renderRowDetails,
    renderRowActions,
    rowDetailsDescription,
    rowDetailsLabel = "Open details",
    rowDetailsTitle,
    rows,
    searchLabel = "Search rows",
    searchPlaceholder = "Search rows",
    searchValue,
    selection,
    selectionLabel,
    selectionActions,
    sorting,
    tableLabel = "Data table",
    toolbarActions,
    visibleColumns,
    ...props
  }: DataTableProps<TData>,
  ref: ForwardedRef<HTMLDivElement>
) {
  const selectionEnabled = enableSelection || selection !== undefined || onSelectionChange !== undefined;
  const searchableColumns = columns.filter(
    (column) => (column.searchable ?? false) || column.searchValue || column.accessor
  );

  const [currentSearchValue, setCurrentSearchValue] = useControllableState({
    controlledValue: searchValue,
    defaultValue: defaultSearchValue,
    onChange: onSearchValueChange
  });
  const [currentSorting, setCurrentSorting] = useControllableState<DataTableSort[]>({
    controlledValue: sorting,
    defaultValue: defaultSorting,
    onChange: onSortingChange
  });
  const [currentSelection, setCurrentSelection] = useControllableState<Record<string, boolean>>({
    controlledValue: selection,
    defaultValue: defaultSelection,
    onChange: onSelectionChange
  });
  const [currentPageIndex, setCurrentPageIndex] = useControllableState({
    controlledValue: pageIndex,
    defaultValue: defaultPageIndex,
    onChange: onPageIndexChange
  });
  const [currentPageSize, setCurrentPageSize] = useControllableState({
    controlledValue: pageSize,
    defaultValue: defaultPageSize,
    onChange: onPageSizeChange
  });
  const [currentDensity, setCurrentDensity] = useControllableState<DataTableDensity>({
    controlledValue: density,
    defaultValue: defaultDensity,
    onChange: onDensityChange
  });
  const [currentVisibleColumns, setCurrentVisibleColumns] = useControllableState<
    Record<string, boolean>
  >({
    controlledValue: visibleColumns,
    defaultValue: defaultVisibleColumns,
    onChange: onVisibleColumnsChange
  });
  const [detailRowId, setDetailRowId] = useState<string | null>(null);

  const resolvedPageSizeOptions = [...new Set([...pageSizeOptions, currentPageSize])].sort(
    (left, right) => left - right
  );

  const globalFilterFn: FilterFn<TData> = (row, _columnId, filterValue) => {
    const query = String(filterValue ?? "").trim().toLowerCase();

    if (query.length === 0) {
      return true;
    }

    return searchableColumns.some((column) =>
      getColumnSearchText(row.original, column).toLowerCase().includes(query)
    );
  };

  const tableColumns: ColumnDef<TData>[] = [
    ...(selectionEnabled
      ? [
          {
            cell: ({ row }) => (
              <Checkbox
                aria-label={`Select row ${row.index + 1}`}
                checked={row.getIsSelected()}
                onCheckedChange={(checked) => {
                  row.toggleSelected(Boolean(checked));
                }}
              />
            ),
            enableGlobalFilter: false,
            enableHiding: false,
            enableSorting: false,
            header: ({ table }) => (
              <Checkbox
                aria-label="Select all rows"
                checked={table.getIsAllPageRowsSelected()}
                onCheckedChange={(checked) => {
                  table.toggleAllPageRowsSelected(Boolean(checked));
                }}
              />
            ),
            id: "__select",
            meta: {
              align: "center",
              width: 56
            } satisfies InternalColumnMeta<TData>
          } satisfies ColumnDef<TData>
        ]
      : []),
    ...(renderRowDetails
      ? [
          {
            cell: ({ row }) => (
              <div {...createSlot("actions")} className="flex items-center justify-end">
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => {
                    setDetailRowId(row.id);
                  }}
                >
                  {rowDetailsLabel}
                </Button>
              </div>
            ),
            enableGlobalFilter: false,
            enableHiding: false,
            enableSorting: false,
            header: () => <span className="sr-only">Row details</span>,
            id: "__details",
            meta: {
              align: "end",
              width: 108
            } satisfies InternalColumnMeta<TData>
          } satisfies ColumnDef<TData>
        ]
      : []),
    ...columns.map((column) => ({
      accessorFn: column.accessor
        ? (row: TData) => getColumnAccessorValue(row, column)
        : undefined,
      cell: ({ row }: CellContext<TData, unknown>) =>
        column.cell
          ? column.cell(row.original)
          : stringifySearchValue(getColumnAccessorValue(row.original, column)),
      enableGlobalFilter: searchableColumns.includes(column),
      enableHiding: column.hideable ?? true,
      enableSorting: column.sortable ?? false,
      header: ({ column: tanstackColumn }: HeaderContext<TData, unknown>) =>
        typeof column.header === "function"
          ? column.header({
              column,
              sorted: tanstackColumn.getIsSorted()
            })
          : column.header,
      id: column.id,
      meta: {
        align: column.align ?? "start",
        sourceColumn: column,
        width: column.width
      } satisfies InternalColumnMeta<TData>,
      sortDescFirst: false
    })),
    ...(renderRowActions
      ? [
          {
            cell: ({ row }) => (
              <div {...createSlot("actions")} className="flex items-center justify-end">
                {renderRowActions(row.original)}
              </div>
            ),
            enableGlobalFilter: false,
            enableHiding: false,
            enableSorting: false,
            header: () => <span className="sr-only">Row actions</span>,
            id: "__actions",
            meta: {
              align: "end",
              width: 88
            } satisfies InternalColumnMeta<TData>
          } satisfies ColumnDef<TData>
        ]
      : [])
  ];

  // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table is the intentional row-model engine behind this source-owned component.
  const table = useReactTable({
    autoResetPageIndex: true,
    columns: tableColumns,
    data: rows,
    enableRowSelection: selectionEnabled,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getRowId: (row, index) => {
      if (getRowId) {
        return getRowId(row, index);
      }

      const candidateId = (row as { id?: unknown }).id;

      if (typeof candidateId === "string" || typeof candidateId === "number") {
        return String(candidateId);
      }

      return String(index);
    },
    getSortedRowModel: getSortedRowModel(),
    globalFilterFn,
    onPaginationChange: (updater) => {
      const nextValue =
        typeof updater === "function"
          ? updater({
              pageIndex: currentPageIndex,
              pageSize: currentPageSize
            })
          : updater;

      setCurrentPageIndex(nextValue.pageIndex);
      setCurrentPageSize(nextValue.pageSize);
    },
    onRowSelectionChange: (updater) => {
      const nextValue =
        typeof updater === "function"
          ? updater(currentSelection as RowSelectionState)
          : updater;

      setCurrentSelection(nextValue);
    },
    onSortingChange: (updater) => {
      const nextValue =
        typeof updater === "function"
          ? updater(currentSorting as SortingState)
          : updater;

      setCurrentSorting(nextValue.map((item) => ({ desc: item.desc, id: item.id })));
    },
    onColumnVisibilityChange: (updater) => {
      const nextValue =
        typeof updater === "function"
          ? updater(currentVisibleColumns)
          : updater;

      setCurrentVisibleColumns(nextValue);
    },
    state: {
      globalFilter: currentSearchValue,
      pagination: {
        pageIndex: currentPageIndex,
        pageSize: currentPageSize
      } satisfies PaginationState,
      columnVisibility: currentVisibleColumns,
      rowSelection: currentSelection,
      sorting: currentSorting as SortingState
    }
  });

  const totalColumns = table.getAllLeafColumns().length;
  const filteredRowCount = table.getFilteredRowModel().rows.length;
  const hideableColumns = table
    .getAllLeafColumns()
    .filter((column) => !column.id.startsWith("__") && column.getCanHide());
  const selectedRows = table.getSelectedRowModel().rows.map((row) => row.original);
  const pageCount = table.getPageCount();
  const isEmpty = !loading && filteredRowCount === 0;
  const shouldRenderSearch = searchableColumns.length > 0;
  const shouldRenderViewOptions = hideableColumns.length > 0;
  const shouldRenderToolbar =
    shouldRenderSearch || toolbarActions !== undefined || shouldRenderViewOptions;
  const pageStart =
    filteredRowCount === 0 ? 0 : currentPageIndex * currentPageSize + 1;
  const pageEnd = Math.min((currentPageIndex + 1) * currentPageSize, filteredRowCount);

  useEffect(() => {
    const maxPageIndex = Math.max(pageCount - 1, 0);

    if (currentPageIndex > maxPageIndex) {
      setCurrentPageIndex(maxPageIndex);
    }
  }, [currentPageIndex, pageCount, setCurrentPageIndex]);

  const detailRow = renderRowDetails
    ? table.getPrePaginationRowModel().rows.find((row) => row.id === detailRowId)
    : undefined;
  const detailRowOriginal = detailRow?.original;
  const resolvedDetailTitle =
    detailRowOriginal && rowDetailsTitle
      ? typeof rowDetailsTitle === "function"
        ? rowDetailsTitle(detailRowOriginal)
        : rowDetailsTitle
      : detailRowOriginal
        ? "Row details"
        : null;
  const resolvedDetailDescription =
    detailRowOriginal && rowDetailsDescription
      ? typeof rowDetailsDescription === "function"
        ? rowDetailsDescription(detailRowOriginal)
        : rowDetailsDescription
      : null;

  return (
    <div
      {...props}
      {...createSlot("root")}
      {...createDataAttributes({
        empty: isEmpty,
        loading,
        selected: selectedRows.length > 0
      })}
      className={cn(dataTableRootVariants(), className)}
      data-density={currentDensity}
      ref={ref}
    >
      {shouldRenderToolbar ? (
        <DataTableToolbar>
          <div className="flex flex-1 flex-wrap items-center gap-3">
            {shouldRenderSearch ? (
              <div className={cn(dataTableSearchContainerVariants())}>
                <DataTableSearch
                  aria-label={searchLabel}
                  onChange={(event) => {
                    setCurrentSearchValue(event.currentTarget.value);
                    setCurrentPageIndex(0);
                  }}
                  placeholder={searchPlaceholder}
                  value={currentSearchValue}
                />
              </div>
            ) : null}
          </div>
          <DataTableFilters>
            {toolbarActions}
            {shouldRenderViewOptions ? (
              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <Button size="sm" variant="subtle">
                    View
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end">
                  <DropdownMenuLabel>Density</DropdownMenuLabel>
                  <DropdownMenuRadioGroup
                    value={currentDensity}
                    onValueChange={(value) => {
                      setCurrentDensity(value as DataTableDensity);
                    }}
                  >
                    <DropdownMenuRadioItem value="comfortable">
                      Comfortable
                    </DropdownMenuRadioItem>
                    <DropdownMenuRadioItem value="compact">
                      Compact
                    </DropdownMenuRadioItem>
                  </DropdownMenuRadioGroup>
                  <DropdownMenuSeparator />
                  <DropdownMenuLabel>Columns</DropdownMenuLabel>
                  {hideableColumns.map((column) => {
                    const meta = column.columnDef.meta as InternalColumnMeta<TData> | undefined;
                    const label =
                      meta?.sourceColumn ? getHeaderLabel(meta.sourceColumn) : column.id;

                    return (
                      <DropdownMenuCheckboxItem
                        checked={column.getIsVisible()}
                        key={column.id}
                        onCheckedChange={(checked) => {
                          column.toggleVisibility(Boolean(checked));
                        }}
                      >
                        {label}
                      </DropdownMenuCheckboxItem>
                    );
                  })}
                </DropdownMenuContent>
              </DropdownMenu>
            ) : null}
          </DataTableFilters>
        </DataTableToolbar>
      ) : null}

      {selectionEnabled && selectedRows.length > 0 ? (
        <DataTableSelectionBar>
          <div className="grid gap-1">
            <p className="text-[0.72rem] font-medium uppercase tracking-[var(--tracking-caps)] text-[color-mix(in_oklch,var(--color-primary)_68%,var(--color-foreground))]">
              Selection ready
            </p>
            <div className="text-sm font-medium text-[var(--color-foreground)]">
              {typeof selectionLabel === "function"
                ? selectionLabel(selectedRows)
                : selectionLabel ?? `${selectedRows.length} selected`}
            </div>
          </div>
          <div
            {...createSlot("actions")}
            className="flex flex-wrap items-center gap-2"
          >
            {selectionActions?.(selectedRows)}
            <Button
              size="sm"
              variant="ghost"
              onClick={() => {
                table.resetRowSelection();
              }}
            >
              Clear selection
            </Button>
          </div>
        </DataTableSelectionBar>
      ) : null}

      <DataTableContent loading={loading}>
        {loading ? <DataTableLoading className="sr-only min-h-0 px-0 py-0" /> : null}
        <div className="overflow-x-auto">
          <DataTableTable aria-label={tableLabel}>
            <DataTableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map((header) => {
                    const meta = header.column.columnDef.meta as InternalColumnMeta<TData> | undefined;
                    const sortState = header.column.getIsSorted();
                    const align: DataTableAlignment = meta?.align ?? "start";

                    return (
                      <DataTableHeaderCell
                        key={header.id}
                        align={align}
                        aria-sort={
                          sortState === "asc"
                            ? "ascending"
                            : sortState === "desc"
                              ? "descending"
                              : undefined
                        }
                        scope="col"
                        density={currentDensity}
                        sortable={header.column.getCanSort()}
                        sort={sortState}
                        style={getColumnWidthStyle(meta?.width)}
                      >
                        {header.isPlaceholder ? null : header.column.getCanSort() ? (
                          <button
                            className={cn(
                              "group inline-flex w-full items-center gap-2 rounded-[calc(var(--ui-control-radius)-0.15rem)] px-2.5 py-2",
                              "outline-none transition-[background-color,box-shadow,color,transform] duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
                              "focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2",
                              "focus-visible:ring-offset-[color-mix(in_oklch,var(--ui-card-default-bg)_82%,white_18%)]",
                              sortState
                                ? "-translate-y-px bg-[color-mix(in_oklch,var(--color-surface-bright)_52%,var(--color-primary-container))] text-[var(--color-foreground)] shadow-[inset_0_1px_0_color-mix(in_oklch,white_42%,transparent)]"
                                : "hover:-translate-y-px hover:bg-[color-mix(in_oklch,var(--ui-card-subtle-bg)_74%,white_26%)] hover:text-[var(--color-foreground)]",
                              align === "end"
                                ? "justify-end"
                                : align === "center"
                                  ? "justify-center"
                                  : "justify-start"
                            )}
                            onClick={header.column.getToggleSortingHandler()}
                            type="button"
                          >
                            <span>{flexRender(header.column.columnDef.header, header.getContext())}</span>
                            <span
                              aria-hidden="true"
                              className={cn(
                                "inline-flex items-center justify-center transition-[color,transform] duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
                                sortState
                                  ? "translate-x-px text-[var(--color-primary)]"
                                  : "text-[var(--color-muted-foreground)] group-hover:translate-x-px group-hover:text-[var(--color-foreground)]"
                              )}
                            >
                              {sortState === "asc" ? (
                                <SortAscendingIcon className="size-3.5" />
                              ) : sortState === "desc" ? (
                                <SortDescendingIcon className="size-3.5" />
                              ) : (
                                <SortUnsortedIcon className="size-3.5" />
                              )}
                            </span>
                            <span className="sr-only">
                              Sort by{" "}
                              {meta?.sourceColumn ? getHeaderLabel(meta.sourceColumn) : header.column.id}
                            </span>
                          </button>
                        ) : (
                          flexRender(header.column.columnDef.header, header.getContext())
                        )}
                      </DataTableHeaderCell>
                    );
                  })}
                </tr>
              ))}
            </DataTableHeader>

            <DataTableBody>
              {loading
                ? Array.from({ length: loadingRowCount }, (_, index) => (
                    <DataTableRow
                      interactive={false}
                      key={`loading-row-${index}`}
                    >
                      {Array.from({ length: totalColumns }, (_, cellIndex) => (
                        <DataTableCell key={`loading-cell-${cellIndex}`}>
                          <Skeleton
                            className={cellIndex === totalColumns - 1 ? "ml-auto w-12" : undefined}
                          />
                        </DataTableCell>
                      ))}
                    </DataTableRow>
                  ))
                : isEmpty
                  ? (
                      <tr>
                        <td colSpan={totalColumns}>
                          {empty ?? (
                            <DataTableEmpty
                              description="Try another search, clear filters, or create a new record to repopulate this view."
                              title="No matching rows"
                            />
                          )}
                        </td>
                      </tr>
                    )
                  : table.getRowModel().rows.map((row) => (
                      <DataTableRow
                        data-selected={row.getIsSelected() ? "" : undefined}
                        key={row.id}
                        selected={row.getIsSelected()}
                      >
                        {row.getVisibleCells().map((cell) => {
                          const meta = cell.column.columnDef.meta as InternalColumnMeta<TData> | undefined;
                          const align: DataTableAlignment = meta?.align ?? "start";

                          return (
                            <DataTableCell
                              align={align}
                              density={currentDensity}
                              key={cell.id}
                              style={getColumnWidthStyle(meta?.width)}
                            >
                              {flexRender(cell.column.columnDef.cell, cell.getContext())}
                            </DataTableCell>
                          );
                        })}
                      </DataTableRow>
                    ))}
            </DataTableBody>
          </DataTableTable>
        </div>

        <DataTablePagination>
          <div className="grid gap-0.5">
            <span className="text-[0.72rem] font-medium uppercase tracking-[var(--tracking-caps)] text-[var(--color-muted-foreground)]">
              Visible rows
            </span>
            <span className="text-sm font-medium text-[var(--color-foreground)]">
              {pageStart}-{pageEnd} of {filteredRowCount}
            </span>
          </div>

          <div className="flex flex-wrap items-center gap-3">
            {resolvedPageSizeOptions.length > 1 ? (
              <div className="flex items-center gap-2 rounded-[var(--radius-full)] bg-[color-mix(in_oklch,var(--ui-card-subtle-bg)_76%,white_24%)] px-2.5 py-1.5 shadow-[var(--ui-control-shadow)]">
                <span className="text-sm text-[var(--color-muted-foreground)]">Rows</span>
                <Select
                  value={String(currentPageSize)}
                  onValueChange={(value) => {
                    setCurrentPageSize(Number(value));
                    setCurrentPageIndex(0);
                  }}
                >
                  <SelectTrigger aria-label="Rows per page" className="h-9 w-[5.5rem] border-0 bg-transparent px-2 shadow-none">
                    <SelectValue placeholder={String(currentPageSize)} />
                  </SelectTrigger>
                  <SelectContent>
                    {resolvedPageSizeOptions.map((option) => (
                      <SelectItem key={option} value={String(option)}>
                        {option}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            ) : null}

            <div className="rounded-[var(--radius-full)] bg-[color-mix(in_oklch,var(--ui-card-subtle-bg)_72%,white_28%)] px-3 py-1.5 text-sm font-medium text-[var(--color-foreground)] shadow-[var(--ui-control-shadow)]">
              Page {Math.min(currentPageIndex + 1, Math.max(pageCount, 1))} of {Math.max(pageCount, 1)}
            </div>

            <div className="flex items-center gap-2 rounded-[var(--radius-full)] bg-[color-mix(in_oklch,var(--ui-card-subtle-bg)_76%,white_24%)] p-1 shadow-[var(--ui-control-shadow)]">
              <Button
                disabled={!table.getCanPreviousPage()}
                size="sm"
                variant="ghost"
                onClick={() => {
                  table.previousPage();
                }}
              >
                Previous
              </Button>
              <Button
                disabled={!table.getCanNextPage()}
                size="sm"
                variant="ghost"
                onClick={() => {
                  table.nextPage();
                }}
              >
                Next
              </Button>
            </div>
          </div>
        </DataTablePagination>
      </DataTableContent>

      {renderRowDetails && detailRowOriginal ? (
        <Sheet
          open={detailRowId !== null}
          onOpenChange={(nextOpen) => {
            if (!nextOpen) {
              setDetailRowId(null);
            }
          }}
        >
          <SheetContent size="lg">
            <SheetHeader>
              <SheetTitle>{resolvedDetailTitle}</SheetTitle>
              {resolvedDetailDescription ? (
                <SheetDescription>{resolvedDetailDescription}</SheetDescription>
              ) : null}
            </SheetHeader>
            <div className="mt-6">{renderRowDetails(detailRowOriginal)}</div>
          </SheetContent>
        </Sheet>
      ) : null}
    </div>
  );
}

type DataTableComponent = <TData>(
  props: DataTableProps<TData> & { ref?: ForwardedRef<HTMLDivElement> }
) => JSX.Element;

export const DataTable = forwardRef(DataTableInner) as DataTableComponent;

function DataTableSearchIcon() {
  return (
    <svg aria-hidden="true" className="size-4" viewBox="0 0 16 16">
      <path
        d="M7.25 12.5a5.25 5.25 0 1 1 0-10.5a5.25 5.25 0 0 1 0 10.5Zm3.75-1.5 3 3"
        fill="none"
        stroke="currentColor"
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth="1.5"
      />
    </svg>
  );
}

export type DataTableToolbarProps = ComponentPropsWithoutRef<"div">;

export const DataTableToolbar = forwardRef<HTMLDivElement, DataTableToolbarProps>(
  function DataTableToolbar({ className, ...props }, ref) {
    return (
      <div
        {...props}
        {...createSlot("toolbar")}
        className={cn(dataTableToolbarVariants(), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableFiltersProps = ComponentPropsWithoutRef<"div">;

export const DataTableFilters = forwardRef<HTMLDivElement, DataTableFiltersProps>(
  function DataTableFilters({ className, ...props }, ref) {
    return (
      <div
        {...props}
        {...createSlot("actions")}
        className={cn("flex flex-wrap items-center justify-end gap-2", className)}
        ref={ref}
      />
    );
  }
);

export type DataTableSearchProps = Omit<InputProps, "size"> & {
  wrapperClassName?: string;
};

export const DataTableSearch = forwardRef<HTMLInputElement, DataTableSearchProps>(
  function DataTableSearch({ className, type = "search", wrapperClassName, ...props }, ref) {
    return (
      <InputGroup className={cn(wrapperClassName)}>
        <InputGroupPrefix>
          <DataTableSearchIcon />
        </InputGroupPrefix>
        <Input {...props} className={className} ref={ref} type={type} />
      </InputGroup>
    );
  }
);

export type DataTableContentProps = ComponentPropsWithoutRef<"div"> &
  VariantProps<typeof dataTableContentVariants>;

export const DataTableContent = forwardRef<HTMLDivElement, DataTableContentProps>(
  function DataTableContent({ className, loading, ...props }, ref) {
    return (
      <div
        {...props}
        {...createSlot("content")}
        {...createDataAttributes({ loading })}
        className={cn(dataTableContentVariants({ loading }), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableTableProps = ComponentPropsWithoutRef<"table">;

export const DataTableTable = forwardRef<HTMLTableElement, DataTableTableProps>(
  function DataTableTable({ className, ...props }, ref) {
    return (
      <table
        {...props}
        {...createSlot("table")}
        className={cn(dataTableTableVariants(), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableHeaderProps = ComponentPropsWithoutRef<"thead">;

export const DataTableHeader = forwardRef<HTMLTableSectionElement, DataTableHeaderProps>(
  function DataTableHeader({ className, ...props }, ref) {
    return (
      <thead
        {...props}
        {...createSlot("header")}
        className={cn(dataTableHeaderVariants(), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableHeaderCellProps = Omit<ComponentPropsWithoutRef<"th">, "align"> &
  VariantProps<typeof dataTableHeaderCellVariants> & {
    density?: DataTableDensity;
    sort?: "asc" | "desc" | false;
  };

export const DataTableHeaderCell = forwardRef<HTMLTableCellElement, DataTableHeaderCellProps>(
  function DataTableHeaderCell(
    {
      align = "start",
      className,
      density = "comfortable",
      sort = false,
      sortable = false,
      ...props
    },
    ref
  ) {
    return (
      <th
        {...props}
        {...createSlot("header")}
        {...createDataAttributes({
          density,
          sort: sort || undefined
        })}
        className={cn(dataTableHeaderCellVariants({ align, density, sortable }), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableBodyProps = ComponentPropsWithoutRef<"tbody">;

export const DataTableBody = forwardRef<HTMLTableSectionElement, DataTableBodyProps>(
  function DataTableBody({ className, ...props }, ref) {
    return (
      <tbody
        {...props}
        className={cn(dataTableBodyVariants(), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableRowProps = ComponentPropsWithoutRef<"tr"> &
  VariantProps<typeof dataTableRowVariants>;

export const DataTableRow = forwardRef<HTMLTableRowElement, DataTableRowProps>(
  function DataTableRow(
    { className, interactive = true, selected = false, ...props },
    ref
  ) {
    return (
      <tr
        {...props}
        {...createSlot("row")}
        {...createDataAttributes({
          selected
        })}
        className={cn(dataTableRowVariants({ interactive, selected }), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableCellProps = Omit<ComponentPropsWithoutRef<"td">, "align"> &
  VariantProps<typeof dataTableCellVariants> & {
    density?: DataTableDensity;
  };

export const DataTableCell = forwardRef<HTMLTableCellElement, DataTableCellProps>(
  function DataTableCell(
    { align = "start", className, density = "comfortable", ...props },
    ref
  ) {
    return (
      <td
        {...props}
        {...createSlot("cell")}
        className={cn(dataTableCellVariants({ align, density }), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableEmptyProps = ComponentPropsWithoutRef<"div"> & {
  actions?: ReactNode;
  description?: ReactNode;
  title?: ReactNode;
};

export const DataTableEmpty = forwardRef<HTMLDivElement, DataTableEmptyProps>(
  function DataTableEmpty(
    {
      actions,
      className,
      description = "No rows match the current search or filter state.",
      title = "Nothing to show",
      ...props
    },
    ref
  ) {
    return (
      <div
        {...props}
        {...createSlot("empty")}
        className={cn(dataTableStatusVariants(), className)}
        ref={ref}
      >
        <EmptyState className="w-full border-none bg-transparent p-0 shadow-none">
          <EmptyStateHeader>
            <EmptyStateTitle>{title}</EmptyStateTitle>
            <EmptyStateDescription>{description}</EmptyStateDescription>
          </EmptyStateHeader>
          {actions ? <EmptyStateActions>{actions}</EmptyStateActions> : null}
        </EmptyState>
      </div>
    );
  }
);

export type DataTableLoadingProps = ComponentPropsWithoutRef<"div"> & {
  description?: ReactNode;
  label?: ReactNode;
};

export const DataTableLoading = forwardRef<HTMLDivElement, DataTableLoadingProps>(
  function DataTableLoading(
    {
      className,
      description = "Preparing the next set of rows and controls.",
      label = "Loading rows",
      ...props
    },
    ref
  ) {
    return (
      <div
        {...props}
        className={cn(dataTableStatusVariants(), className)}
        ref={ref}
        role="status"
      >
        <div className="grid justify-items-center gap-3 text-center">
          <Spinner aria-label={String(label)} size="lg" tone="primary" />
          <div className="space-y-1">
            <p className="text-sm font-medium text-[var(--color-foreground)]">{label}</p>
            <p className="text-sm leading-6 text-[var(--color-muted-foreground)]">
              {description}
            </p>
          </div>
        </div>
      </div>
    );
  }
);

export type DataTablePaginationProps = ComponentPropsWithoutRef<"div">;

export const DataTablePagination = forwardRef<HTMLDivElement, DataTablePaginationProps>(
  function DataTablePagination({ className, ...props }, ref) {
    return (
      <div
        {...props}
        {...createSlot("pagination")}
        className={cn(dataTablePaginationVariants(), className)}
        ref={ref}
      />
    );
  }
);

export type DataTableSelectionBarProps = ComponentPropsWithoutRef<"div">;

export const DataTableSelectionBar = forwardRef<HTMLDivElement, DataTableSelectionBarProps>(
  function DataTableSelectionBar({ className, ...props }, ref) {
    return (
      <div
        {...props}
        className={cn(dataTableSelectionBarVariants(), className)}
        ref={ref}
      />
    );
  }
);
