/**
 * @file DataTable.tsx - Data table display component with Bootstrap 5 styling and features including sorting, filtering, searching, pagination, row selection, and expandable rows.
 */

import {
  type ChangeEvent,
  type Dispatch,
  Fragment,
  type ReactNode,
  type SetStateAction,
  useEffect,
  useMemo,
  useState,
} from 'react';
import {
  Collapse,
  Dropdown,
  Form,
  OverlayTrigger,
  Table,
  Tooltip,
} from 'react-bootstrap';
import {
  type ColumnDef,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  type PaginationState,
  type RowSelectionState,
  type SortingState,
  useReactTable,
} from '@tanstack/react-table';
import {
  ArrowDown,
  ArrowUp,
  CornerDownRight,
  Filter,
  FoldVertical,
  UnfoldVertical,
} from 'lucide-react';
import Fuse from 'fuse.js';
import { useMediaQuery } from 'react-responsive';
import { breakpoints } from '../utils/bootstrapBreakpoints.ts';
import {
  getStoredTablePagination,
  setStoredTablePagination,
} from '../utils/localStorage.ts';
import { CustomPaginationControls } from './shared/CustomPaginationControls.tsx';
import { useHasVerticalScrollbar } from '../hooks/useHasVerticalScrollbar.ts';
import { Trans, useTranslation } from 'react-i18next';

/**
 * Available page sizes for table pagination.
 * Users can select how many rows to display per page.
 */
const TablePageSizes = [10, 25, 50] as const;

/**
 * Type representing one of the allowed page size values.
 */
export type TablePageSizeType = (typeof TablePageSizes)[number];

/**
 * Props interface for the DataTable component.
 *
 * @template T - The type of data objects displayed in the table rows
 * @template R - The type of data objects in expandable row content (if using expansion feature)
 */
interface TableProps<T extends object, R extends object> {
  /**
   * Column definitions following TanStack Table's ColumnDef format.
   * Each column should have an accessorKey that matches a property in the data objects.
   */
  columns: ColumnDef<T>[];

  /**
   * Array of data objects to display in the table.
   * Each object represents one row.
   */
  data: T[];

  /**
   * Configuration for row selection behavior.
   * - 'none': No row selection
   * - 'single': Only one row can be selected at a time
   * - 'multiple': Multiple rows can be selected simultaneously
   *
   * @default { rule: 'none' }
   */
  selection?:
    | { rule: 'none' }
    | ((
        | {
            rule: 'single';

            /** Callback fired when a row is selected, receives the selected row data */
            setSelectedRow: (selectedRow: T) => void;
          }
        | {
            rule: 'multiple';

            /** Callback fired when selection changes, receives all selected row data */
            setSelectedRows: (selectedRows: T[]) => void;
          }
      ) & {
        /**
         * Optional callback to receive the internal row selection setter function.
         * This allows parent components to programmatically control selection state.
         *
         * @example
         * ```tsx
         * const [rowSelectionSetter, setRowSelectionSetter] = useState<Dispatch<SetStateAction<RowSelectionState>>>();
         * ```
         * @example
         * ```
         * onRowSelectionSetterReady: (setter) => setRowSelectionSetter(() => setter)
         * ```
         */
        onRowSelectionSetterReady?: (
          setter: Dispatch<SetStateAction<RowSelectionState>>
        ) => void;
      });

  /**
   * Configuration for expandable rows with nested content.
   * When provided, rows can be expanded to show additional data.
   */
  expansion?: {
    /**
     * Map of parent row identifiers to their associated child data.
     * The key should match the value of parentAccessorKey for each row.
     */
    data: Map<number, R[]>;

    /**
     * The accessor key used to match parent rows to their expansion data.
     * This should correspond to a unique identifier in the row data (e.g., 'id', 'userid').
     */
    parentAccessorKey: string;

    /**
     * Render function for the expanded content.
     * Receives the matched child data array and should return the JSX to display.
     */
    children: (data: R[] | undefined) => ReactNode;
  };

  /**
   * The accessor key of the column to sort by initially.
   * Defaults to the first column's accessorKey.
   */
  initialSortAccessorKey?: string;

  /**
   * Initial sort direction for the default sorted column.
   *
   * @default 'descending'
   */
  initialSortDirection?: 'ascending' | 'descending';

  /**
   * Optional toolbar buttons to display above the table.
   * Supports up to 2 buttons on each side.
   */
  toolbarButtons?: {
    /** Buttons displayed on the left side of the toolbar */
    left?: readonly [ReactNode?, ReactNode?];
    /** Buttons displayed on the right side of the toolbar */
    right?: readonly [ReactNode?, ReactNode?];
  };

  /**
   * Default number of rows per page.
   * Must be one of the values in TablePageSizes (10, 25, or 50).
   *
   * @default 10
   */
  defaultPageSize?: TablePageSizeType;

  /**
   * Local storage key for persisting the user's page size preference.
   * When provided, the selected page size will be saved and restored.
   */
  pageSizeStateKey?: string;

  /**
   * Whether to pad the table with empty rows to maintain consistent height.
   * Useful for preventing layout shifts when page content varies.
   *
   * @default false
   */
  padding?: boolean;

  /**
   * Maximum number of padding rows to add.
   * Only applies when padding is true.
   * Defaults to the current page size.
   */
  maxPadding?: number;
}

/**
 * A fully-featured data table component built with TanStack Table and Bootstrap 5.
 *
 * Features:
 * - Sorting: Click column headers to sort ascending/descending
 * - Filtering: Per-column dropdown filters with multi-select
 * - Search: Global fuzzy search across all columns using Fuse.js
 * - Pagination: Configurable page sizes with persistent preferences
 * - Row Selection: Single or multiple row selection modes
 * - Row Expansion: Expandable rows for displaying nested content
 * - Responsive: Adapts layout for mobile screens
 *
 * @template T - The type of data objects displayed in table rows
 * @template R - The type of data objects in expandable row content
 *
 * @example
 * ```tsx
 * <DataTable
 *   columns={[
 *     { accessorKey: 'name', header: 'Name' },
 *     { accessorKey: 'email', header: 'Email' },
 *   ]}
 *   data={users}
 *   selection={{ rule: 'single', setSelectedRow: handleSelect }}
 * />
 * ```
 */
export function DataTable<T extends object, R extends object>({
  columns,
  data,
  selection = { rule: 'none' },
  expansion,
  // @ts-expect-error accessorKey exists
  initialSortAccessorKey = columns[0].accessorKey as string,
  initialSortDirection = 'descending',
  toolbarButtons = { left: [], right: [] },
  defaultPageSize = 10,
  pageSizeStateKey,
  padding = false,
  maxPadding,
}: TableProps<T, R>) {
  // Initialize page size from localStorage or use the provided default
  const [pageSize, setPageSize] = useState<number>(
    getStoredTablePagination(pageSizeStateKey as string) || defaultPageSize
  );

  /**
   * Handles page size changes from the dropdown selector.
   * Updates local state, pagination state, and persists to localStorage.
   */
  const updatePageSize = (event: ChangeEvent<HTMLSelectElement>) => {
    const value = Number(event.target.value);

    setPageSize(value);
    setPagination({ ...pagination, pageSize: value });
    if (pageSizeStateKey) {
      setStoredTablePagination(pageSizeStateKey, value as TablePageSizeType);
    }
  };

  // Map of cell identifiers to their display values, used to track cell content changes
  const [cellValues, setCellValues] = useState<Map<string, string>>(new Map());
  // Current sorting configuration (which column and direction)
  const [sorting, setSorting] = useState<SortingState>([
    {
      id: initialSortAccessorKey,
      // Initial sorting direction for "ID" column
      desc: initialSortDirection === 'descending',
    },
  ]);
  // Active filters for each column (maps column key to set of allowed values)
  const [filters, setFilters] = useState<Record<keyof T, Set<any>>>(
    {} as Record<keyof T, Set<any>>
  );
  // Current page index and size for pagination
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: pageSize,
  });
  // Global search query string for fuzzy matching
  const [searchQuery, setSearchQuery] = useState<string>('');

  // Selected rows state (maps row indices to selection status)
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
  // Expose the row selection setter to parent components if requested
  useEffect(() => {
    if (selection.rule !== 'none' && selection.onRowSelectionSetterReady) {
      selection.onRowSelectionSetterReady(setRowSelection);
    }
  }, [selection]);
  // Notify parent component when row selection changes
  useEffect(() => {
    const selectedRows = table
      .getSelectedRowModel()
      .rows.map((row) => row.original);

    if (selection.rule === 'single') {
      selection.setSelectedRow(selectedRows[0]);
    } else if (selection.rule === 'multiple') {
      selection.setSelectedRows(selectedRows);
    }
  }, [rowSelection]);

  // Track which rows are expanded (showing their collapse content)
  const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
  const [shownCollapseRows, setShownCollapseRows] = useState<Set<string>>(
    new Set()
  );

  /**
   * Rebuilds the cell values map from source data.
   * This is needed to track changes and display formatted values.
   */
  const updateCellValues = (sourceData: T[]) => {
    const newCellValues = new Map<string, string>();

    sourceData.forEach((row, index) => {
      columns.forEach((column) => {
        // @ts-expect-error accessorKey exists
        const columnKey = column.accessorKey as string;
        const cellId = `${index}_${columnKey}`;
        // Display "N/A" for missing or null values
        const rawValue =
          columnKey in row ? row[columnKey as keyof T] : undefined;
        const displayValue =
          rawValue !== undefined && rawValue !== null
            ? String(rawValue)
            : 'N/A';
        newCellValues.set(cellId, displayValue);
      });
    });

    setCellValues(newCellValues);
  };

  // Update cell values and clean up stale filters when data changes
  useEffect(() => {
    updateCellValues(data);

    // Remove filters that reference values no longer present in the data
    setFilters((prevFilters) => {
      const newFilters = {} as Record<keyof T, Set<any>>;
      const availableKeys = new Set(Object.keys(data[0] || {}));

      Object.keys(prevFilters).forEach((key) => {
        const typedKey = key as keyof T;

        // Only keep filters for columns that still exist in the data
        if (availableKeys.has(key)) {
          const availableValues = new Set(data.map((row) => row[typedKey]));

          // Keep only filter values that exist in the new data
          newFilters[typedKey] = new Set(
            [...prevFilters[typedKey]].filter((value) =>
              availableValues.has(value)
            )
          );

          // Remove the filter entirely if no values remain
          if (newFilters[typedKey].size === 0) {
            delete newFilters[typedKey];
          }
        }
      });

      return newFilters;
    });
  }, [data]);

  /**
   * Computes unique values for each column, used to populate filter dropdowns.
   * Recalculates whenever data or columns change.
   */
  const uniqueValues = useMemo(() => {
    const values: Record<keyof T, Set<any>> = {} as Record<keyof T, Set<any>>;

    // Initialize empty sets for all columns
    columns.forEach((column) => {
      // @ts-expect-error accessorKey exists
      const key = column.accessorKey as keyof T;
      values[key] = new Set();
    });

    // Collect unique values from all rows
    data.forEach((row) => {
      columns.forEach((column) => {
        // @ts-expect-error accessorKey exists
        const key = column.accessorKey as keyof T;
        const value = key in row ? row[key] : undefined;
        // Treat undefined/null as "N/A" for filtering purposes
        values[key].add(value === undefined || value === null ? 'N/A' : value);
      });
    });
    return values;
  }, [data, columns]);

  /**
   * Applies column filters and sorting to the data.
   * Returns a new array with filtered and sorted results.
   */
  const refreshFilteredData = (
    data: T[],
    filters: Record<keyof T, Set<any>>,
    sorting: SortingState
  ) => {
    // First, filter rows based on active column filters
    const filteredData = data.filter((row) =>
      (Object.entries(filters) as [keyof T, Set<any>][]).every(
        ([key, allowedValues]) => {
          const rowValue = key in row ? row[key] : undefined;
          const compareValue =
            rowValue === undefined || rowValue === null ? 'N/A' : rowValue;
          return allowedValues.has(compareValue);
        }
      )
    );

    // Then sort the filtered results
    return [...filteredData].sort((a, b) => {
      for (const { id, desc } of sorting) {
        const aValue = a[id as keyof T];
        const bValue = b[id as keyof T];

        if (aValue < bValue) {
          return desc ? 1 : -1;
        }
        if (aValue > bValue) {
          return desc ? -1 : 1;
        }
      }
      // Maintain original order if values are equal
      return 0;
    });
  };

  // Memoized filtered and sorted data
  const filteredData = useMemo(
    () => refreshFilteredData(data, filters, sorting),
    [data, filters, sorting]
  );

  /**
   * Toggles a filter value on or off for a specific column.
   * Called when a checkbox in the filter dropdown is clicked.
   */
  const toggleFilter = (columnId: keyof T, value: any) => {
    setFilters((prev) => {
      const newFilters = { ...prev };

      // Initialize filter with all values if not yet set
      if (!newFilters[columnId]) {
        newFilters[columnId] = new Set(uniqueValues[columnId]);
      }

      // Toggle the specific value
      if (newFilters[columnId].has(value)) {
        newFilters[columnId].delete(value);
      } else {
        newFilters[columnId].add(value);
      }

      // Remove the filter if all values are selected (no filtering needed)
      if (newFilters[columnId].size === uniqueValues[columnId]?.size) {
        delete newFilters[columnId];
      }

      return { ...newFilters };
    });
  };

  /**
   * Determines the state of the "Select All" checkbox in filter dropdowns.
   * Returns 'checked' if all selected, 'unchecked' if none, 'indeterminate' if partial.
   */
  const getFilterMultiToggleState = (columnId: keyof T) => {
    // No filter exists or all values selected = fully checked
    if (
      !filters[columnId] ||
      filters[columnId].size === uniqueValues[columnId]?.size
    ) {
      return 'checked';
    }

    // Filter exists but empty = none selected
    if (!filters[columnId].size) {
      return 'unchecked';
    }

    // Some but not all selected
    return 'indeterminate';
  };

  // Configure Fuse.js for fuzzy global search
  const fuse = useMemo(() => {
    return new Fuse(filteredData, {
      // @ts-expect-error accessorKey exists on column definitions
      keys: columns.map((column) => column.accessorKey as string),
      threshold: 0, // Exact matching only
      ignoreLocation: true, // Match anywhere in the string
      includeScore: true,
    });
  }, [filteredData, columns]);

  /**
   * Applies global search to the filtered data.
   * Returns matching rows or all filtered data if no search query.
   */
  const searchedData = useMemo(() => {
    let searchedData;

    if (searchQuery) {
      searchedData = fuse.search(searchQuery).map((result) => result.item);
    } else {
      searchedData = filteredData;
    }

    updateCellValues(searchedData);
    return searchedData;
  }, [filteredData, searchQuery, fuse]);

  /**
   * Manages the expansion state of rows with nested content.
   * Handles both expanding/collapsing and the collapse animation lifecycle.
   */
  const updateExpansionStates = (
    rowId: string,
    rowIsExpanded: boolean,
    isCollapseRow: boolean
  ) => {
    const newExpandedRows = new Set(expandedRows);
    const newShownCollapseRows = new Set(shownCollapseRows);

    if (!isCollapseRow) {
      // Toggle expansion state for the main row
      if (rowIsExpanded) {
        newExpandedRows.delete(rowId);
      } else {
        newExpandedRows.add(rowId);
        newShownCollapseRows.add(rowId);
      }
      setExpandedRows(newExpandedRows);
    } else {
      // Hide the collapse row after animation completes
      newShownCollapseRows.delete(rowId);
    }

    setShownCollapseRows(newShownCollapseRows);
  };

  // Initialize TanStack Table with all configuration
  const table = useReactTable({
    data: searchedData,
    columns,
    state: { sorting, pagination, rowSelection },
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onSortingChange: setSorting,
    onPaginationChange: setPagination,
    onRowSelectionChange: setRowSelection,
    enableSortingRemoval: false, // Always sort by at least one column
    enableRowSelection: selection.rule !== 'none',
    enableMultiRowSelection: selection.rule === 'multiple',
    autoResetPageIndex: false,
  });

  const totalPages = table.getPageCount();
  const isEmpty = table.getRowModel().rows.length === 0;
  const isMobileMd = useMediaQuery({ maxWidth: breakpoints.md - 1 });
  const tooltipFixed = !useHasVerticalScrollbar();

  const { t } = useTranslation(undefined, {
    keyPrefix: 'components.data_table',
  });

  // Return a beautiful Bootstrap table
  // Required knowledge: https://tanstack.com/table/latest/docs/introduction
  return (
    <Fragment>
      {/* Mobile layout: all toolbar buttons grouped together */}
      {isMobileMd && (
        <div className={'mb-2'}>
          <div className={'d-flex flex-wrap gap-2'}>
            {toolbarButtons?.left?.map((button, index) => (
              <div key={index}>{button}</div>
            ))}
            {toolbarButtons?.right?.map((button, index) => (
              <div key={index}>{button}</div>
            ))}
          </div>
        </div>
      )}

      {/* Toolbar with search, buttons, page size selector, and pagination */}
      <div
        className={
          'd-flex flex-column flex-md-row justify-content-between align-items-md-center gap-2 mb-2'
        }
      >
        {/* Left toolbar buttons (desktop only) */}
        {!isMobileMd &&
          toolbarButtons?.left?.map((button, index) => (
            <div key={index}>{button}</div>
          ))}

        {/* Global search input */}
        <Form.Control
          type={'text'}
          placeholder={`${t('search_bar.placeholder')}...`}
          className={'flex-grow-1'}
          value={searchQuery}
          onChange={(event) => setSearchQuery(event.target.value)}
        />

        {/* Right toolbar buttons (desktop only) */}
        {!isMobileMd &&
          toolbarButtons?.right?.map((button, index) => (
            <div key={index}>{button}</div>
          ))}

        {/* Page size selector dropdown */}
        <div className={`${isMobileMd ? 'd-flex justify-content-end' : ''}`}>
          <Form.Select
            value={pageSize}
            onChange={updatePageSize}
            style={{ minWidth: '5rem', maxWidth: '5rem' }}
          >
            <option disabled>{t('pagination.select.default')}</option>
            {TablePageSizes.map((size) => (
              <option key={size} value={size}>
                {size}
              </option>
            ))}
          </Form.Select>
        </div>

        {/* Pagination controls */}
        <div className={'d-flex justify-content-end'}>
          <CustomPaginationControls
            table={table}
            totalPages={totalPages}
            isMobile={isMobileMd}
          />
        </div>
      </div>

      {/* Main data table */}
      <Table striped bordered hover responsive className={'mb-0'}>
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {/* Row selection checkbox column header */}
              {selection.rule !== 'none' && (
                <th
                  className={'align-middle'}
                  style={{ whiteSpace: 'nowrap', minWidth: 'fit-content' }}
                >
                  <span
                    className={
                      'd-flex justify-content-center align-items-center'
                    }
                  >
                    <Form.Check
                      type={'checkbox'}
                      checked={table.getIsAllRowsSelected()}
                      ref={(element) => {
                        if (element) {
                          element.indeterminate = table.getIsSomeRowsSelected();
                        }
                      }}
                      onChange={table.getToggleAllRowsSelectedHandler()}
                      disabled={selection.rule === 'single'}
                    />
                  </span>
                </th>
              )}

              {/* Row expansion toggle column header */}
              {expansion && (
                <th
                  className={'align-middle'}
                  style={{ whiteSpace: 'nowrap', minWidth: 'fit-content' }}
                >
                  <OverlayTrigger
                    placement={'top'}
                    overlay={
                      <Tooltip
                        className={tooltipFixed ? 'position-fixed' : undefined}
                      >
                        <Trans
                          t={t}
                          i18nKey={'table_header.row_expansion.tooltip'}
                          components={{
                            icon: <UnfoldVertical size={16} />,
                          }}
                        />
                      </Tooltip>
                    }
                  >
                    <span
                      className={
                        'd-flex justify-content-center align-items-center'
                      }
                    >
                      <CornerDownRight size={16} />
                    </span>
                  </OverlayTrigger>
                </th>
              )}

              {/* Data column headers */}
              {headerGroup.headers.map((header) => {
                const column = header.column;
                const columnId = column.id as keyof T;

                const multiToggleState = getFilterMultiToggleState(columnId);

                return (
                  <th
                    key={header.id}
                    className={'align-middle'}
                    style={{ whiteSpace: 'nowrap', minWidth: 'fit-content' }}
                  >
                    <div
                      className={
                        'd-flex justify-content-between align-items-center'
                      }
                    >
                      {/* Column header text with sort toggle */}
                      <span
                        onClick={
                          isEmpty ? undefined : column.getToggleSortingHandler()
                        }
                        role={isEmpty ? undefined : 'button'} // pointer: cursor
                        className={
                          'align-middle ' +
                          (column.getCanFilter() ? 'me-3' : '')
                        }
                      >
                        {column.columnDef.header as string}{' '}
                        {/* Sort direction indicators */}
                        {column.getCanSort() && (
                          <span>
                            <ArrowUp
                              size={16}
                              className={
                                column.getIsSorted() === 'asc'
                                  ? 'opacity-100'
                                  : 'opacity-50'
                              }
                            />
                            <ArrowDown
                              size={16}
                              className={
                                column.getIsSorted() === 'desc'
                                  ? 'opacity-100'
                                  : 'opacity-50'
                              }
                            />
                          </span>
                        )}
                      </span>

                      {/* Column filter dropdown */}
                      {column.getCanFilter() && (
                        <span className={'float-end'} role={'button'}>
                          <Dropdown align={'end'} autoClose={'outside'}>
                            <Dropdown.Toggle
                              variant={'outline-dark'}
                              size={'sm'}
                              disabled={
                                isEmpty && !(filters[columnId]?.size === 0)
                              }
                            >
                              <Filter size={16} />
                            </Dropdown.Toggle>
                            <Dropdown.Menu
                              renderOnMount
                              popperConfig={{ strategy: 'fixed' }}
                            >
                              {/* Select/Unselect All toggle */}
                              <Dropdown.Item
                                as={'div'}
                                onClick={() => {
                                  if (multiToggleState === 'checked') {
                                    // Unselect all
                                    setFilters((prev) => ({
                                      ...prev,
                                      [columnId]: new Set(),
                                    }));
                                  } else {
                                    // Select all
                                    setFilters((prev) => ({
                                      ...prev,
                                      [columnId]: new Set(
                                        uniqueValues[columnId]
                                      ),
                                    }));
                                  }
                                }}
                              >
                                <Form.Check
                                  type={'checkbox'}
                                  label={
                                    multiToggleState === 'checked'
                                      ? `${t('table_header.filter_toggle.dropdown.top_checkbox.checked')}`
                                      : `${t('table_header.filter_toggle.dropdown.top_checkbox.default')}`
                                  }
                                  checked={multiToggleState === 'checked'}
                                  ref={(element) => {
                                    if (element) {
                                      element.indeterminate =
                                        multiToggleState === 'indeterminate';
                                    }
                                  }}
                                  readOnly
                                />
                              </Dropdown.Item>
                              <Dropdown.Divider />

                              {/* Individual filter value checkboxes */}
                              <div
                                style={{
                                  maxHeight: '22.5rem',
                                  overflowY: 'auto',
                                }}
                              >
                                {Array.from(uniqueValues[columnId] || []).map(
                                  (value) => (
                                    <Dropdown.Item
                                      key={value}
                                      as={'div'}
                                      onClick={() =>
                                        toggleFilter(columnId, value)
                                      }
                                    >
                                      <Form.Check
                                        type={'checkbox'}
                                        label={
                                          !String(value).length ||
                                          String(value) === 'null' ||
                                          String(value) === 'undefined'
                                            ? 'N/A'
                                            : String(value)
                                        }
                                        checked={
                                          filters[columnId]?.has(value) ?? true
                                        }
                                        readOnly
                                      />
                                    </Dropdown.Item>
                                  )
                                )}
                              </div>
                            </Dropdown.Menu>
                          </Dropdown>
                        </span>
                      )}
                    </div>
                  </th>
                );
              })}
            </tr>
          ))}
        </thead>
        <tbody>
          {!isEmpty ? (
            <Fragment>
              {/* Data rows */}
              {table.getRowModel().rows.map((row, index, array) => {
                const rowData = row.original;
                const rowPrimaryKey = Number(
                  rowData[expansion?.parentAccessorKey as keyof T]
                );

                // Find expansion data for this row if applicable
                const matchingCollapseRows =
                  expansion?.data.get(rowPrimaryKey) || [];

                const rowCanExpand = Boolean(
                  expansion && matchingCollapseRows.length
                );
                const rowIsExpanded = expandedRows.has(row.id);
                const showCollapseRow = shownCollapseRows.has(row.id);

                return (
                  <Fragment key={row.id}>
                    {/* Main data row */}
                    <tr
                      onClick={
                        selection.rule !== 'none' && !expansion
                          ? row.getToggleSelectedHandler()
                          : selection.rule === 'none' && rowCanExpand
                            ? () =>
                                updateExpansionStates(
                                  row.id,
                                  rowIsExpanded,
                                  false
                                )
                            : undefined
                      }
                      style={
                        expansion
                          ? {
                              borderBottomWidth:
                                !rowIsExpanded && index !== array.length - 1
                                  ? 0
                                  : 1,
                            }
                          : undefined
                      }
                    >
                      {/* Row selection checkbox cell */}
                      {selection.rule !== 'none' && (
                        <td className={'align-middle'}>
                          <span
                            className={
                              'd-flex justify-content-center align-items-center'
                            }
                          >
                            <Form.Check
                              type={'checkbox'}
                              checked={row.getIsSelected()}
                              disabled={!row.getCanSelect()}
                              onChange={row.getToggleSelectedHandler()}
                            />
                          </span>
                        </td>
                      )}

                      {/* Row expansion toggle cell */}
                      {expansion && (
                        <td
                          className={'align-middle'}
                          onClick={
                            rowCanExpand
                              ? () =>
                                  updateExpansionStates(
                                    row.id,
                                    rowIsExpanded,
                                    false
                                  )
                              : undefined
                          }
                          role={rowCanExpand ? 'button' : undefined}
                        >
                          <span
                            className={
                              'd-flex justify-content-center align-items-center'
                            }
                          >
                            {rowIsExpanded ? (
                              <FoldVertical size={16} />
                            ) : (
                              <UnfoldVertical
                                size={16}
                                className={
                                  rowCanExpand ? undefined : 'opacity-50'
                                }
                              />
                            )}
                          </span>
                        </td>
                      )}

                      {/* Data cells */}
                      {row.getVisibleCells().map((cell) => {
                        const cellValue =
                          String(cellValues.get(cell.id)).length &&
                          String(cellValues.get(cell.id)) !== 'null' &&
                          String(cellValues.get(cell.id)) !== 'undefined'
                            ? String(cellValues.get(cell.id))
                            : 'N/A';

                        return (
                          <td key={cell.id} className={'align-middle'}>
                            {cellValue}
                          </td>
                        );
                      })}
                    </tr>

                    {/* Expandable content row */}
                    {expansion && (
                      <Fragment>
                        {/* Collapse container row */}
                        <tr
                          className={
                            rowIsExpanded || showCollapseRow
                              ? undefined
                              : 'd-none'
                          }
                          id={'collapse-row-' + index}
                          style={{
                            borderTopWidth: 0,
                            borderBottomWidth: 0,
                            backgroundColor: 'transparent',
                          }}
                        >
                          <td
                            colSpan={
                              columns.length +
                              (selection?.rule !== 'none' ? 1 : 0) +
                              (expansion ? 1 : 0)
                            }
                            className={'p-0 w-100'}
                            style={{ maxWidth: 0 }}
                          >
                            <Collapse
                              in={rowIsExpanded}
                              className={'bg-white'}
                              onExited={() =>
                                updateExpansionStates(
                                  row.id,
                                  rowIsExpanded,
                                  true
                                )
                              }
                            >
                              <div>
                                <div className={'p-3'}>
                                  {expansion.children(matchingCollapseRows)}
                                </div>
                              </div>
                            </Collapse>
                          </td>
                        </tr>
                        {/* Hidden row to maintain striped pattern */}
                        <tr className={'d-none'}></tr>
                      </Fragment>
                    )}
                  </Fragment>
                );
              })}

              {/* Padding rows to maintain consistent table height */}
              {padding &&
                table.getRowModel().rows.length < pageSize &&
                Array.from({
                  length:
                    (maxPadding || pageSize) - table.getRowModel().rows.length,
                }).map((_, index) => (
                  <tr key={`empty-row-${index}`}>
                    {table.getAllColumns().map((column) => (
                      <td key={column.id}>&nbsp;</td>
                    ))}
                    {selection.rule !== 'none' && <td>&nbsp;</td>}
                    {expansion && <td>&nbsp;</td>}
                  </tr>
                ))}
            </Fragment>
          ) : (
            <Fragment>
              {padding ? (
                // Empty state with padding rows
                Array.from({
                  length: pageSize,
                }).map((_, index) => (
                  <tr key={`empty-row-${index}`}>
                    {index === 0 ? (
                      <td
                        colSpan={
                          columns.length +
                          (selection.rule !== 'none' ? 1 : 0) +
                          (expansion ? 1 : 0)
                        }
                        className={'text-center'}
                      >
                        {t('table_body.no_data_text')}
                      </td>
                    ) : (
                      <>
                        {table.getAllColumns().map((column) => (
                          <td key={column.id}>&nbsp;</td>
                        ))}
                        {selection.rule !== 'none' && <td>&nbsp;</td>}
                        {expansion && <td>&nbsp;</td>}
                      </>
                    )}
                  </tr>
                ))
              ) : (
                // Simple empty state message
                <tr>
                  <td
                    colSpan={
                      columns.length +
                      (selection.rule !== 'none' ? 1 : 0) +
                      (expansion ? 1 : 0)
                    }
                    className={'text-center p-3'}
                  >
                    {t('table_body.no_data_text')}
                  </td>
                </tr>
              )}
            </Fragment>
          )}
        </tbody>
      </Table>
    </Fragment>
  );
}
