// Component adapted from https://github.com/bvaughn/react-window/issues/826

import clsx from 'clsx';
import { motion } from 'motion/react';
import React, {
    type JSXElementConstructor,
    memo,
    ReactElement,
    Ref,
    RefObject,
    useCallback,
    useEffect,
    useId,
    useMemo,
    useRef,
    useState,
    useSyncExternalStore,
} from 'react';
import { useParams } from 'react-router';
import { type CellComponentProps, Grid } from 'react-window-v2';

import styles from './item-table-list.module.css';

import { appendLayoutFillColumn } from '/@/renderer/components/item-list/helpers/append-layout-fill-column';
import { createExtractRowId } from '/@/renderer/components/item-list/helpers/extract-row-id';
import { useDefaultItemListControls } from '/@/renderer/components/item-list/helpers/item-list-controls';
import {
    ItemListStateActions,
    ItemListStateItemWithRequiredProperties,
    useItemListState,
} from '/@/renderer/components/item-list/helpers/item-list-state';
import { parseTableColumns } from '/@/renderer/components/item-list/helpers/parse-table-columns';
import { useListHotkeys } from '/@/renderer/components/item-list/helpers/use-list-hotkeys';
import { useContainerWidthTracking } from '/@/renderer/components/item-list/item-table-list/hooks/use-container-width-tracking';
import { useRowInteractionDelegate } from '/@/renderer/components/item-list/item-table-list/hooks/use-row-interaction-delegate';
import { useStickyGroupRowPositioning } from '/@/renderer/components/item-list/item-table-list/hooks/use-sticky-group-row-positioning';
import { useStickyHeaderPositioning } from '/@/renderer/components/item-list/item-table-list/hooks/use-sticky-header-positioning';
import { useStickyTableGroupRows } from '/@/renderer/components/item-list/item-table-list/hooks/use-sticky-table-group-rows';
import { useStickyTableHeader } from '/@/renderer/components/item-list/item-table-list/hooks/use-sticky-table-header';
import { useTableColumnModel } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-column-model';
import { useTableImperativeHandle } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-imperative-handle';
import { useTableInitialScroll } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-initial-scroll';
import { useTableKeyboardNavigation } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-keyboard-navigation';
import { useTablePaneSync } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-pane-sync';
import { useTableRowModel } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-row-model';
import { useTableScrollToIndex } from '/@/renderer/components/item-list/item-table-list/hooks/use-table-scroll-to-index';
import {
    estimateAlbumGroupContentHeight,
    getAlbumGroupHeightKey,
    getAlbumGroupRowCount,
    getAlbumGroupSpanHeight,
    getAlbumGroupStartRowIndex,
    isLastInAlbumGroup,
    ItemTableListColumn,
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import {
    ItemTableListColumnResizeLiveProvider,
    type ItemTableListConfig,
    ItemTableListConfigProvider,
    ItemTableListStoreProvider,
    useItemTableListColumnResizeLiveState,
} from '/@/renderer/components/item-list/item-table-list/item-table-list-context';
import {
    MemoizedCellRouter,
    useColumnCellComponents,
} from '/@/renderer/components/item-list/item-table-list/memoized-cell-router';
import {
    createTableScrollShadowStore,
    type TableScrollShadowStore,
} from '/@/renderer/components/item-list/item-table-list/table-scroll-shadow-store';
import {
    ItemControls,
    ItemListHandle,
    ItemTableListColumnConfig,
} from '/@/renderer/components/item-list/types';
import { PlayerContext, usePlayer } from '/@/renderer/features/player/context/player-context';
import {
    useAlbumGroupImageSize,
    useAlbumGroupItems,
    useAlbumGroupShowFavoriteRating,
    useAlbumGroupVerticalLayout,
    usePlayerStore,
} from '/@/renderer/store';
import { animationProps } from '/@/shared/components/animations/animation-props';
import { useFocusWithin } from '/@/shared/hooks/use-focus-within';
import { useMergedRef } from '/@/shared/hooks/use-merged-ref';
import { LibraryItem } from '/@/shared/types/domain-types';
import { TableColumn } from '/@/shared/types/types';

/**
 * Type guard to check if an item has the required properties (id and serverId)
 * Similar to the type guard used in ItemCard
 */
const hasRequiredItemProperties = (item: unknown): item is { id: string; serverId: string } => {
    return (
        typeof item === 'object' &&
        item !== null &&
        'id' in item &&
        typeof (item as any).id === 'string' &&
        '_serverId' in item &&
        typeof (item as any)._serverId === 'string'
    );
};

/**
 * Type guard to check if an item has the required properties for ItemListStateItemWithRequiredProperties
 */
const hasRequiredStateItemProperties = (
    item: unknown,
): item is ItemListStateItemWithRequiredProperties => {
    return (
        typeof item === 'object' &&
        item !== null &&
        'id' in item &&
        typeof (item as any).id === 'string' &&
        '_serverId' in item &&
        typeof (item as any)._serverId === 'string' &&
        '_itemType' in item &&
        typeof (item as any)._itemType === 'string'
    );
};

export enum TableItemSize {
    COMPACT = 40,
    DEFAULT = 64,
    LARGE = 88,
}

const ItemTableScrollShadowLeft = memo(function ItemTableScrollShadowLeft({
    enableScrollShadow,
    pinnedLeftColumnCount,
    scrollShadowStore,
}: {
    enableScrollShadow: boolean;
    pinnedLeftColumnCount: number;
    scrollShadowStore: TableScrollShadowStore;
}) {
    const { showLeftShadow } = useSyncExternalStore(
        scrollShadowStore.subscribe,
        scrollShadowStore.getSnapshot,
    );
    if (pinnedLeftColumnCount <= 0 || !enableScrollShadow || !showLeftShadow) return null;
    return <div className={styles.itemTableLeftScrollShadow} />;
});

ItemTableScrollShadowLeft.displayName = 'ItemTableScrollShadowLeft';

const ItemTableScrollShadowRight = memo(function ItemTableScrollShadowRight({
    enableScrollShadow,
    pinnedRightColumnCount,
    scrollShadowStore,
}: {
    enableScrollShadow: boolean;
    pinnedRightColumnCount: number;
    scrollShadowStore: TableScrollShadowStore;
}) {
    const { showRightShadow } = useSyncExternalStore(
        scrollShadowStore.subscribe,
        scrollShadowStore.getSnapshot,
    );
    if (pinnedRightColumnCount <= 0 || !enableScrollShadow || !showRightShadow) return null;
    return <div className={styles.itemTableRightScrollShadow} />;
});

ItemTableScrollShadowRight.displayName = 'ItemTableScrollShadowRight';

interface VirtualizedTableGridProps {
    albumGroupContentHeights: Map<string, number>;
    calculatedColumnWidths: number[];
    CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
    data: unknown[];
    dataWithGroups: (null | unknown)[];
    enableScrollShadow: boolean;
    estimatedAlbumGroupContentHeight: number;
    getItem?: (index: number) => undefined | unknown;
    headerHeight: number;
    mergedRowRef: React.Ref<HTMLDivElement>;
    onRangeChanged?: ItemTableListProps['onRangeChanged'];
    parsedColumns: ReturnType<typeof parseTableColumns>;
    pinnedLeftColumnCount: number;
    pinnedLeftColumnRef: React.RefObject<HTMLDivElement | null>;
    pinnedRightColumnCount: number;
    pinnedRightColumnRef: React.RefObject<HTMLDivElement | null>;
    pinnedRowCount: number;
    pinnedRowRef: React.RefObject<HTMLDivElement | null>;
    scrollShadowStore: TableScrollShadowStore;
    setAlbumGroupContentHeight: (groupKey: string, height: number) => void;
    tableConfig: ItemTableListConfig;
    totalColumnCount: number;
    totalRowCount: number;
}

const VirtualizedTableGrid = ({
    albumGroupContentHeights,
    calculatedColumnWidths,
    CellComponent,
    data,
    dataWithGroups,
    enableScrollShadow,
    estimatedAlbumGroupContentHeight,
    getItem,
    headerHeight,
    mergedRowRef,
    onRangeChanged,
    parsedColumns,
    pinnedLeftColumnCount,
    pinnedLeftColumnRef,
    pinnedRightColumnCount,
    pinnedRightColumnRef,
    pinnedRowCount,
    pinnedRowRef,
    scrollShadowStore,
    setAlbumGroupContentHeight,
    tableConfig,
    totalColumnCount,
    totalRowCount,
}: VirtualizedTableGridProps) => {
    const { enableHeader, enableRowHoverHighlight, getRowHeight, groups } = tableConfig;
    const albumGroupImageSize = useAlbumGroupImageSize();
    const albumGroupVerticalLayout = useAlbumGroupVerticalLayout();
    const hoverDelegateRef = useRef<HTMLDivElement | null>(null);

    useRowInteractionDelegate({
        containerRef: hoverDelegateRef,
        enableRowHoverHighlight,
    });

    const columnWidth = useCallback(
        (index: number) => calculatedColumnWidths[index],
        [calculatedColumnWidths],
    );

    const columnWidthMemoized = useCallback(
        (index: number) => columnWidth(index + pinnedLeftColumnCount),
        [columnWidth, pinnedLeftColumnCount],
    );

    const groupHeaderInfoByRowIndex = useMemo(() => {
        if (!groups || groups.length === 0) return undefined;

        const map = new Map<number, { groupIndex: number; startDataIndex: number }>();
        const headerOffset = enableHeader ? 1 : 0;
        let cumulativeDataIndex = 0;

        for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
            const groupHeaderIndex = headerOffset + cumulativeDataIndex + groupIndex;
            map.set(groupHeaderIndex, { groupIndex, startDataIndex: cumulativeDataIndex });
            cumulativeDataIndex += groups[groupIndex].itemCount;
        }

        return map;
    }, [groups, enableHeader]);

    const rowHeightMemoized = useCallback(
        (index: number, cellProps: TableItemProps) => {
            const adjustedIndex = index + pinnedRowCount;
            return getRowHeight(adjustedIndex, cellProps);
        },
        [getRowHeight, pinnedRowCount],
    );

    const pinnedRightColumnWidthMemoized = useCallback(
        (index: number) => columnWidth(index + pinnedLeftColumnCount + totalColumnCount),
        [columnWidth, pinnedLeftColumnCount, totalColumnCount],
    );

    const getGroupRenderData = useCallback(() => data, [data]);

    // Calculate pinned column widths for group header positioning
    const pinnedLeftColumnWidths = useMemo(() => {
        return Array.from({ length: pinnedLeftColumnCount }, (_, i) => columnWidth(i));
    }, [pinnedLeftColumnCount, columnWidth]);

    const pinnedRightColumnWidths = useMemo(() => {
        return Array.from({ length: pinnedRightColumnCount }, (_, i) =>
            columnWidth(i + pinnedLeftColumnCount + totalColumnCount),
        );
    }, [pinnedRightColumnCount, pinnedLeftColumnCount, totalColumnCount, columnWidth]);

    const groupHeaderRowIndexes = useMemo(() => {
        if (!groupHeaderInfoByRowIndex || groupHeaderInfoByRowIndex.size === 0) return [];
        return Array.from(groupHeaderInfoByRowIndex.keys()).sort((a, b) => a - b);
    }, [groupHeaderInfoByRowIndex]);

    const adjustedRowIndexCacheRef = useRef<{ lastRowIndex: number; pos: number }>({
        lastRowIndex: -1,
        pos: 0,
    });

    useEffect(() => {
        adjustedRowIndexCacheRef.current = { lastRowIndex: -1, pos: 0 };
    }, [enableHeader, groupHeaderRowIndexes, groups]);

    const getAdjustedRowIndex = useCallback(
        (rowIndex: number) => {
            if (!groups || groups.length === 0) {
                if (enableHeader && rowIndex === 0) return 0;
                return enableHeader ? rowIndex : rowIndex + 1;
            }

            if (enableHeader && rowIndex === 0) return 0;
            if (groupHeaderInfoByRowIndex?.has(rowIndex)) return 0;

            const headerOffset = enableHeader ? 1 : 0;
            const cache = adjustedRowIndexCacheRef.current;

            // Count group header rows strictly before this rowIndex.
            let pos: number;
            if (cache.lastRowIndex !== -1 && rowIndex >= cache.lastRowIndex) {
                pos = cache.pos;
                while (
                    pos < groupHeaderRowIndexes.length &&
                    groupHeaderRowIndexes[pos] < rowIndex
                ) {
                    pos++;
                }
            } else {
                // upperBound(groupHeaderRowIndexes, rowIndex - 1)
                let lo = 0;
                let hi = groupHeaderRowIndexes.length;
                const target = rowIndex - 1;
                while (lo < hi) {
                    const mid = (lo + hi) >>> 1;
                    if (groupHeaderRowIndexes[mid] <= target) lo = mid + 1;
                    else hi = mid;
                }
                pos = lo;
            }

            cache.lastRowIndex = rowIndex;
            cache.pos = pos;

            const groupHeadersBefore = pos;
            const dataIndexZeroBased = rowIndex - headerOffset - groupHeadersBefore;
            return dataIndexZeroBased + 1;
        },
        [enableHeader, groupHeaderInfoByRowIndex, groupHeaderRowIndexes, groups],
    );

    const getRowItem = useCallback(
        (rowIndex: number): null | undefined | unknown => {
            // Header row
            if (enableHeader && rowIndex === 0) return null;
            // Group header rows are represented as null in the row model
            if (groupHeaderInfoByRowIndex?.has(rowIndex)) return null;

            if (!groups || groups.length === 0) {
                const dataIndex = enableHeader ? rowIndex - 1 : rowIndex;
                return getItem ? getItem(dataIndex) : dataWithGroups[rowIndex];
            }

            const headerOffset = enableHeader ? 1 : 0;

            // Count group header rows strictly before this rowIndex (upperBound on groupHeaderRowIndexes)
            let lo = 0;
            let hi = groupHeaderRowIndexes.length;
            const target = rowIndex - 1;
            while (lo < hi) {
                const mid = (lo + hi) >>> 1;
                if (groupHeaderRowIndexes[mid] <= target) lo = mid + 1;
                else hi = mid;
            }
            const groupHeadersBefore = lo;

            const dataIndex = rowIndex - headerOffset - groupHeadersBefore;
            return getItem ? getItem(dataIndex) : undefined;
        },
        [
            dataWithGroups,
            enableHeader,
            getItem,
            groupHeaderInfoByRowIndex,
            groupHeaderRowIndexes,
            groups,
        ],
    );

    const itemProps: TableItemProps = useMemo(
        () => ({
            albumGroupContentHeights,
            albumGroupImageSize,
            albumGroupVerticalLayout,
            calculatedColumnWidths,
            cellPadding: tableConfig.cellPadding,
            columns: tableConfig.columns,
            controls: tableConfig.controls,
            data: dataWithGroups,
            enableAlternateRowColors: tableConfig.enableAlternateRowColors,
            enableColumnReorder: tableConfig.enableColumnReorder,
            enableColumnResize: tableConfig.enableColumnResize,
            enableDrag: tableConfig.enableDrag,
            enableExpansion: tableConfig.enableExpansion,
            enableHeader: tableConfig.enableHeader,
            enableHorizontalBorders: tableConfig.enableHorizontalBorders,
            enableRowHoverHighlight: tableConfig.enableRowHoverHighlight,
            enableSelection: tableConfig.enableSelection,
            enableVerticalBorders: tableConfig.enableVerticalBorders,
            estimatedAlbumGroupContentHeight,
            getAdjustedRowIndex,
            getGroupRenderData,
            getRowHeight: tableConfig.getRowHeight,
            getRowItem,
            groupHeaderInfoByRowIndex,
            groups: tableConfig.groups,
            hasAlbumGroupColumn: parsedColumns.some((col) => col.id === TableColumn.ALBUM_GROUP),
            internalState: tableConfig.internalState,
            itemType: tableConfig.itemType,
            pinnedLeftColumnCount,
            pinnedLeftColumnWidths,
            pinnedRightColumnCount,
            pinnedRightColumnWidths,
            playerContext: tableConfig.playerContext,
            playlistId: tableConfig.playlistId,
            setAlbumGroupContentHeight,
            size: tableConfig.size,
            startRowIndex: tableConfig.startRowIndex,
            tableId: tableConfig.tableId,
        }),
        [
            albumGroupContentHeights,
            albumGroupImageSize,
            albumGroupVerticalLayout,
            calculatedColumnWidths,
            dataWithGroups,
            estimatedAlbumGroupContentHeight,
            getAdjustedRowIndex,
            getGroupRenderData,
            getRowItem,
            groupHeaderInfoByRowIndex,
            parsedColumns,
            pinnedLeftColumnCount,
            pinnedLeftColumnWidths,
            pinnedRightColumnCount,
            pinnedRightColumnWidths,
            setAlbumGroupContentHeight,
            tableConfig,
        ],
    );

    const pinnedLeftGridMinWidthPx = useMemo(() => {
        let sum = 0;
        for (let i = 0; i < pinnedLeftColumnCount; i++) {
            sum += calculatedColumnWidths[i] ?? 0;
        }
        return sum;
    }, [calculatedColumnWidths, pinnedLeftColumnCount]);

    const pinnedRightGridMinWidthPx = useMemo(() => {
        let sum = 0;
        const start = pinnedLeftColumnCount + totalColumnCount;
        for (let i = 0; i < pinnedRightColumnCount; i++) {
            sum += calculatedColumnWidths[start + i] ?? 0;
        }
        return sum;
    }, [calculatedColumnWidths, pinnedLeftColumnCount, pinnedRightColumnCount, totalColumnCount]);

    const pinnedRowsMinHeightPx = useMemo(() => {
        let sum = 0;
        for (let i = 0; i < pinnedRowCount; i++) {
            sum += getRowHeight(i, itemProps);
        }
        return sum;
    }, [getRowHeight, itemProps, pinnedRowCount]);

    const PinnedRowCell = useCallback(
        (cellProps: CellComponentProps & TableItemProps) => {
            return (
                <CellComponent
                    {...cellProps}
                    columnIndex={cellProps.columnIndex + pinnedLeftColumnCount}
                />
            );
        },
        [pinnedLeftColumnCount, CellComponent],
    );

    const PinnedColumnCell = useCallback(
        (cellProps: CellComponentProps & TableItemProps) => {
            return <CellComponent {...cellProps} rowIndex={cellProps.rowIndex + pinnedRowCount} />;
        },
        [pinnedRowCount, CellComponent],
    );

    const PinnedRightColumnCell = useCallback(
        (cellProps: CellComponentProps & TableItemProps) => {
            return (
                <CellComponent
                    {...cellProps}
                    columnIndex={cellProps.columnIndex + pinnedLeftColumnCount + totalColumnCount}
                    rowIndex={cellProps.rowIndex + pinnedRowCount}
                />
            );
        },
        [pinnedLeftColumnCount, pinnedRowCount, totalColumnCount, CellComponent],
    );

    const PinnedRightIntersectionCell = useCallback(
        (cellProps: CellComponentProps & TableItemProps) => {
            return (
                <CellComponent
                    {...cellProps}
                    columnIndex={cellProps.columnIndex + pinnedLeftColumnCount + totalColumnCount}
                />
            );
        },
        [pinnedLeftColumnCount, totalColumnCount, CellComponent],
    );

    const RowCell = useCallback(
        (cellProps: CellComponentProps<TableItemProps>) => {
            return (
                <CellComponent
                    {...cellProps}
                    columnIndex={cellProps.columnIndex + pinnedLeftColumnCount}
                    rowIndex={cellProps.rowIndex + pinnedRowCount}
                />
            );
        },
        [pinnedLeftColumnCount, pinnedRowCount, CellComponent],
    );

    const handleOnCellsRendered = useCallback(
        (items: {
            columnStartIndex: number;
            columnStopIndex: number;
            rowStartIndex: number;
            rowStopIndex: number;
        }) => {
            onRangeChanged?.({
                startIndex: items.rowStartIndex,
                stopIndex: items.rowStopIndex,
            });
        },
        [onRangeChanged],
    );

    return (
        <div className={styles.itemTableContainer} ref={hoverDelegateRef}>
            <div
                className={styles.itemTablePinnedColumnsGridContainer}
                style={
                    {
                        '--header-height': `${headerHeight}px`,
                        minWidth: `${pinnedLeftGridMinWidthPx}px`,
                    } as React.CSSProperties
                }
            >
                {!!(pinnedLeftColumnCount || pinnedRowCount) && (
                    <div
                        className={clsx(styles.itemTablePinnedIntersectionGridContainer, {
                            [styles.withHeader]: enableHeader,
                        })}
                        style={{
                            minHeight: `${pinnedRowsMinHeightPx}px`,
                            overflow: 'visible',
                        }}
                    >
                        <Grid
                            cellComponent={CellComponent as any}
                            cellProps={itemProps}
                            className={styles.noScrollbar}
                            columnCount={pinnedLeftColumnCount}
                            columnWidth={columnWidth}
                            rowCount={pinnedRowCount}
                            rowHeight={getRowHeight}
                        />
                    </div>
                )}
                {!!pinnedLeftColumnCount && (
                    <div
                        className={styles.itemTablePinnedColumnsContainer}
                        ref={pinnedLeftColumnRef}
                    >
                        <Grid
                            cellComponent={PinnedColumnCell}
                            cellProps={itemProps}
                            className={clsx(styles.noScrollbar, styles.height100)}
                            columnCount={pinnedLeftColumnCount}
                            columnWidth={columnWidth}
                            rowCount={totalRowCount}
                            rowHeight={(index, cellProps) => {
                                return getRowHeight(index + pinnedRowCount, cellProps);
                            }}
                        />
                    </div>
                )}
            </div>
            <div
                className={styles.itemTablePinnedRowsContainer}
                style={
                    {
                        '--header-height': `${headerHeight}px`,
                    } as React.CSSProperties
                }
            >
                {!!pinnedRowCount && (
                    <div
                        className={clsx(styles.itemTablePinnedRowsGridContainer, {
                            [styles.withHeader]: enableHeader,
                        })}
                        ref={pinnedRowRef}
                        style={
                            {
                                '--header-height': `${headerHeight}px`,
                                minHeight: `${pinnedRowsMinHeightPx}px`,
                                overflow: 'hidden',
                            } as React.CSSProperties
                        }
                    >
                        <Grid
                            cellComponent={PinnedRowCell}
                            cellProps={itemProps}
                            className={styles.noScrollbar}
                            columnCount={totalColumnCount}
                            columnWidth={(index) => {
                                return columnWidth(index + pinnedLeftColumnCount);
                            }}
                            rowCount={pinnedRowCount}
                            rowHeight={getRowHeight}
                        />
                    </div>
                )}
                <div className={styles.itemTableGridContainer} ref={mergedRowRef}>
                    <Grid
                        cellComponent={RowCell}
                        cellProps={itemProps}
                        className={styles.height100}
                        columnCount={totalColumnCount}
                        columnWidth={columnWidthMemoized}
                        onCellsRendered={handleOnCellsRendered}
                        rowCount={totalRowCount}
                        rowHeight={rowHeightMemoized}
                    />
                    <ItemTableScrollShadowLeft
                        enableScrollShadow={enableScrollShadow}
                        pinnedLeftColumnCount={pinnedLeftColumnCount}
                        scrollShadowStore={scrollShadowStore}
                    />
                    <ItemTableScrollShadowRight
                        enableScrollShadow={enableScrollShadow}
                        pinnedRightColumnCount={pinnedRightColumnCount}
                        scrollShadowStore={scrollShadowStore}
                    />
                </div>
            </div>
            {!!pinnedRightColumnCount && (
                <div
                    className={styles.itemTablePinnedColumnsGridContainer}
                    style={
                        {
                            '--header-height': `${headerHeight}px`,
                            minWidth: `${pinnedRightGridMinWidthPx}px`,
                        } as React.CSSProperties
                    }
                >
                    {!!(pinnedRightColumnCount || pinnedRowCount) && (
                        <div
                            className={clsx(styles.itemTablePinnedIntersectionGridContainer, {
                                [styles.withHeader]: enableHeader,
                            })}
                            style={{
                                minHeight: `${pinnedRowsMinHeightPx}px`,
                                overflow: 'visible',
                            }}
                        >
                            <Grid
                                cellComponent={PinnedRightIntersectionCell}
                                cellProps={itemProps}
                                className={styles.noScrollbar}
                                columnCount={pinnedRightColumnCount}
                                columnWidth={(index) => {
                                    return columnWidth(
                                        index + pinnedLeftColumnCount + totalColumnCount,
                                    );
                                }}
                                rowCount={pinnedRowCount}
                                rowHeight={getRowHeight}
                            />
                        </div>
                    )}
                    <div
                        className={styles.itemTablePinnedRightColumnsContainer}
                        ref={pinnedRightColumnRef}
                    >
                        <Grid
                            cellComponent={PinnedRightColumnCell}
                            cellProps={itemProps}
                            className={clsx(styles.noScrollbar, styles.height100)}
                            columnCount={pinnedRightColumnCount}
                            columnWidth={pinnedRightColumnWidthMemoized}
                            rowCount={totalRowCount}
                            rowHeight={rowHeightMemoized}
                        />
                    </div>
                </div>
            )}
        </div>
    );
};

VirtualizedTableGrid.displayName = 'VirtualizedTableGrid';

function shallowEqualNumberArrays(a: number[], b: number[]): boolean {
    if (a === b) return true;
    if (a.length !== b.length) return false;
    for (let i = 0; i < a.length; i++) {
        if (a[i] !== b[i]) return false;
    }
    return true;
}

const MemoizedVirtualizedTableGrid = memo(VirtualizedTableGrid, (prevProps, nextProps) => {
    return (
        shallowEqualNumberArrays(
            prevProps.calculatedColumnWidths,
            nextProps.calculatedColumnWidths,
        ) &&
        prevProps.albumGroupContentHeights === nextProps.albumGroupContentHeights &&
        prevProps.estimatedAlbumGroupContentHeight === nextProps.estimatedAlbumGroupContentHeight &&
        prevProps.setAlbumGroupContentHeight === nextProps.setAlbumGroupContentHeight &&
        prevProps.tableConfig === nextProps.tableConfig &&
        prevProps.data === nextProps.data &&
        prevProps.dataWithGroups === nextProps.dataWithGroups &&
        prevProps.enableScrollShadow === nextProps.enableScrollShadow &&
        prevProps.getItem === nextProps.getItem &&
        prevProps.headerHeight === nextProps.headerHeight &&
        prevProps.mergedRowRef === nextProps.mergedRowRef &&
        prevProps.onRangeChanged === nextProps.onRangeChanged &&
        prevProps.parsedColumns === nextProps.parsedColumns &&
        prevProps.pinnedLeftColumnCount === nextProps.pinnedLeftColumnCount &&
        prevProps.pinnedLeftColumnRef === nextProps.pinnedLeftColumnRef &&
        prevProps.pinnedRightColumnCount === nextProps.pinnedRightColumnCount &&
        prevProps.pinnedRightColumnRef === nextProps.pinnedRightColumnRef &&
        prevProps.pinnedRowCount === nextProps.pinnedRowCount &&
        prevProps.pinnedRowRef === nextProps.pinnedRowRef &&
        prevProps.scrollShadowStore === nextProps.scrollShadowStore &&
        prevProps.totalColumnCount === nextProps.totalColumnCount &&
        prevProps.totalRowCount === nextProps.totalRowCount &&
        prevProps.CellComponent === nextProps.CellComponent
    );
});

MemoizedVirtualizedTableGrid.displayName = 'MemoizedVirtualizedTableGrid';

export interface TableGroupHeader {
    itemCount: number;
    render: (props: {
        data: unknown[];
        groupIndex: number;
        index: number;
        internalState: ItemListStateActions;
        startDataIndex: number;
    }) => ReactElement;
}

export interface TableItemProps {
    adjustedRowIndexMap?: Map<number, number>;
    albumGroupContentHeights?: Map<string, number>;
    albumGroupImageSize?: number;
    albumGroupVerticalLayout?: boolean;
    calculatedColumnWidths?: number[];
    cellPadding?: ItemTableListProps['cellPadding'];
    columns: ItemTableListColumnConfig[];
    controls: ItemControls;
    data: ItemTableListProps['data'];
    enableAlternateRowColors?: ItemTableListProps['enableAlternateRowColors'];
    enableColumnReorder?: boolean;
    enableColumnResize?: boolean;
    enableDrag?: ItemTableListProps['enableDrag'];
    enableDragScroll?: boolean;
    enableExpansion?: ItemTableListProps['enableExpansion'];
    enableHeader?: ItemTableListProps['enableHeader'];
    enableHorizontalBorders?: ItemTableListProps['enableHorizontalBorders'];
    enableRowHoverHighlight?: ItemTableListProps['enableRowHoverHighlight'];
    enableSelection?: ItemTableListProps['enableSelection'];
    enableVerticalBorders?: ItemTableListProps['enableVerticalBorders'];
    estimatedAlbumGroupContentHeight?: number;
    getAdjustedRowIndex?: (rowIndex: number) => number;
    getGroupRenderData?: () => unknown[];
    getRowHeight: (index: number, cellProps: TableItemProps) => number;
    getRowItem?: (rowIndex: number) => null | undefined | unknown;
    groupHeaderInfoByRowIndex?: Map<number, { groupIndex: number; startDataIndex: number }>;
    groups?: TableGroupHeader[];
    hasAlbumGroupColumn?: boolean;
    internalState: ItemListStateActions;
    itemType: ItemTableListProps['itemType'];
    onRowClick?: (item: any, event: React.MouseEvent<HTMLDivElement>) => void;
    pinnedLeftColumnCount?: number;
    pinnedLeftColumnWidths?: number[];
    pinnedRightColumnCount?: number;
    pinnedRightColumnWidths?: number[];
    playerContext: PlayerContext;
    playlistId?: string;
    setAlbumGroupContentHeight?: (groupKey: string, height: number) => void;
    size?: ItemTableListProps['size'];
    startRowIndex?: number;
    tableId: string;
}

interface ItemTableListProps {
    activeRowId?: string;
    autoFitColumns?: boolean;
    autoScrollToActiveRow?: boolean;
    CellComponent?: JSXElementConstructor<CellComponentProps<TableItemProps>>;
    cellPadding?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
    columns: ItemTableListColumnConfig[];
    data: unknown[];
    enableAlternateRowColors?: boolean;
    enableDrag?: boolean;
    enableDragScroll?: boolean;
    enableEntranceAnimation?: boolean;
    enableExpansion?: boolean;
    enableHeader?: boolean;
    enableHorizontalBorders?: boolean;
    enableRowHoverHighlight?: boolean;
    enableScrollShadow?: boolean;
    enableSelection?: boolean;
    enableSelectionDialog?: boolean;
    enableStickyGroupRows?: boolean;
    enableStickyHeader?: boolean;
    enableVerticalBorders?: boolean;
    getItem?: (index: number) => undefined | unknown;
    getItemIndex?: (rowId: string) => number | undefined;
    getLoadedItems?: () => unknown[];
    getRowId?: ((item: unknown) => string) | string;
    groups?: TableGroupHeader[];
    headerHeight?: number;
    initialTop?: {
        behavior?: 'auto' | 'smooth';
        to: number;
        type: 'index' | 'offset';
    };
    itemCount?: number;
    itemType: LibraryItem;
    onColumnReordered?: (
        columnIdFrom: TableColumn,
        columnIdTo: TableColumn,
        edge: 'bottom' | 'left' | 'right' | 'top' | null,
    ) => void;
    onColumnResized?: (columnId: TableColumn, width: number) => void;
    onRangeChanged?: (range: { startIndex: number; stopIndex: number }) => void;
    onScrollEnd?: (offset: number, internalState: ItemListStateActions) => void;
    overrideControls?: Partial<ItemControls>;
    ref?: Ref<ItemListHandle>;
    rowHeight?: ((index: number, cellProps: TableItemProps) => number) | number;
    size?: 'compact' | 'default' | 'large';
    startRowIndex?: number;
}

const ItemTableListStickyUI = memo(
    ({
        calculatedColumnWidths,
        CellComponent,
        containerRef,
        data,
        enableHeader,
        enableStickyGroupRows,
        enableStickyHeader,
        getRowHeightWrapper,
        groups,
        headerHeight,
        internalState,
        parsedColumns,
        pinnedLeftColumnCount,
        pinnedLeftColumnRef,
        pinnedRightColumnCount,
        pinnedRightColumnRef,
        pinnedRowRef,
        rowHeight,
        rowRef,
        size,
        stickyHeaderItemProps,
        totalColumnCount,
    }: {
        calculatedColumnWidths: number[];
        CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
        containerRef: RefObject<HTMLDivElement | null>;
        data: unknown[];
        enableHeader: boolean;
        enableStickyGroupRows: boolean;
        enableStickyHeader: boolean;
        getRowHeightWrapper: (index: number) => number;
        groups?: TableGroupHeader[];
        headerHeight: number;
        internalState: ItemListStateActions;
        parsedColumns: ReturnType<typeof parseTableColumns>;
        pinnedLeftColumnCount: number;
        pinnedLeftColumnRef: RefObject<HTMLDivElement | null>;
        pinnedRightColumnCount: number;
        pinnedRightColumnRef: RefObject<HTMLDivElement | null>;
        pinnedRowRef: RefObject<HTMLDivElement | null>;
        rowHeight?: ((index: number, cellProps: TableItemProps) => number) | number;
        rowRef: RefObject<HTMLDivElement | null>;
        size: 'compact' | 'default' | 'large';
        stickyHeaderItemProps: TableItemProps;
        totalColumnCount: number;
    }) => {
        const stickyHeaderRef = useRef<HTMLDivElement | null>(null);
        const stickyGroupRowRef = useRef<HTMLDivElement | null>(null);
        const stickyHeaderLeftRef = useRef<HTMLDivElement | null>(null);
        const stickyHeaderMainRef = useRef<HTMLDivElement | null>(null);
        const stickyHeaderRightRef = useRef<HTMLDivElement | null>(null);

        const { shouldShowStickyHeader, stickyTop } = useStickyTableHeader({
            containerRef,
            enabled: enableHeader && enableStickyHeader,
            headerRef: pinnedRowRef,
            mainGridRef: rowRef,
            pinnedLeftColumnRef,
            pinnedRightColumnRef,
            stickyHeaderMainRef,
        });

        useStickyHeaderPositioning({
            containerRef,
            shouldShowStickyHeader,
            stickyHeaderRef,
        });

        const {
            shouldShowStickyGroupRow,
            stickyGroupIndex,
            stickyTop: stickyGroupTop,
        } = useStickyTableGroupRows({
            containerRef,
            enabled: enableStickyGroupRows && !!groups && groups.length > 0,
            getRowHeight: getRowHeightWrapper,
            groups,
            headerHeight,
            mainGridRef: rowRef,
            shouldShowStickyHeader,
            stickyHeaderTop: stickyTop,
        });

        const shouldRenderStickyGroupRow = shouldShowStickyGroupRow;

        useStickyGroupRowPositioning({
            containerRef,
            shouldRenderStickyGroupRow,
            stickyGroupRowRef,
        });

        const StickyHeader = useMemo(() => {
            if (!shouldShowStickyHeader || !enableHeader) {
                return null;
            }

            const pinnedLeftWidth = calculatedColumnWidths
                .slice(0, pinnedLeftColumnCount)
                .reduce((sum, width) => sum + width, 0);
            const mainWidth = calculatedColumnWidths
                .slice(pinnedLeftColumnCount, pinnedLeftColumnCount + totalColumnCount)
                .reduce((sum, width) => sum + width, 0);
            const pinnedRightWidth = calculatedColumnWidths
                .slice(pinnedLeftColumnCount + totalColumnCount)
                .reduce((sum, width) => sum + width, 0);

            return (
                <div
                    className={styles.stickyHeader}
                    ref={stickyHeaderRef}
                    style={{
                        top: `${stickyTop}px`,
                    }}
                >
                    <div className={styles.stickyHeaderRow}>
                        {pinnedLeftColumnCount > 0 && (
                            <div
                                className={clsx(
                                    styles.stickyHeaderSection,
                                    styles.stickyHeaderPinnedLeft,
                                )}
                                ref={stickyHeaderLeftRef}
                                style={{
                                    flex: '0 1 auto',
                                    minWidth: `${pinnedLeftWidth}px`,
                                    overflow: 'visible',
                                }}
                            >
                                {parsedColumns
                                    .filter((col) => col.pinned === 'left')
                                    .map((col) => {
                                        const columnIndex = parsedColumns.findIndex(
                                            (c) => c === col,
                                        );
                                        return (
                                            <CellComponent
                                                ariaAttributes={{
                                                    'aria-colindex': columnIndex + 1,
                                                    role: 'gridcell',
                                                }}
                                                columnIndex={columnIndex}
                                                key={col.id}
                                                rowIndex={0}
                                                style={{
                                                    height: headerHeight,
                                                    width: calculatedColumnWidths[columnIndex],
                                                }}
                                                {...stickyHeaderItemProps}
                                            />
                                        );
                                    })}
                            </div>
                        )}
                        <div
                            className={clsx(
                                styles.stickyHeaderSection,
                                styles.stickyHeaderMain,
                                styles.noScrollbar,
                            )}
                            ref={stickyHeaderMainRef}
                            style={{
                                flex: '1 1 auto',
                                minWidth: 0,
                                overflowX: 'auto',
                                overflowY: 'hidden',
                            }}
                        >
                            <div
                                style={{
                                    display: 'flex',
                                    minWidth: `${mainWidth}px`,
                                }}
                            >
                                {parsedColumns
                                    .filter((col) => col.pinned === null)
                                    .map((col) => {
                                        const columnIndex = parsedColumns.findIndex(
                                            (c) => c === col,
                                        );
                                        return (
                                            <CellComponent
                                                ariaAttributes={{
                                                    'aria-colindex': columnIndex + 1,
                                                    role: 'gridcell',
                                                }}
                                                columnIndex={columnIndex}
                                                key={col.id}
                                                rowIndex={0}
                                                style={{
                                                    flexShrink: 0,
                                                    height: headerHeight,
                                                    width: calculatedColumnWidths[columnIndex],
                                                }}
                                                {...stickyHeaderItemProps}
                                            />
                                        );
                                    })}
                            </div>
                        </div>
                        {pinnedRightColumnCount > 0 && (
                            <div
                                className={clsx(
                                    styles.stickyHeaderSection,
                                    styles.stickyHeaderPinnedRight,
                                )}
                                ref={stickyHeaderRightRef}
                                style={{
                                    flex: '0 1 auto',
                                    minWidth: `${pinnedRightWidth}px`,
                                    overflow: 'visible',
                                }}
                            >
                                {parsedColumns
                                    .filter((col) => col.pinned === 'right')
                                    .map((col) => {
                                        const columnIndex = parsedColumns.findIndex(
                                            (c) => c === col,
                                        );
                                        return (
                                            <CellComponent
                                                ariaAttributes={{
                                                    'aria-colindex': columnIndex + 1,
                                                    role: 'gridcell',
                                                }}
                                                columnIndex={columnIndex}
                                                key={col.id}
                                                rowIndex={0}
                                                style={{
                                                    height: headerHeight,
                                                    width: calculatedColumnWidths[columnIndex],
                                                }}
                                                {...stickyHeaderItemProps}
                                            />
                                        );
                                    })}
                            </div>
                        )}
                    </div>
                </div>
            );
        }, [
            shouldShowStickyHeader,
            enableHeader,
            stickyTop,
            calculatedColumnWidths,
            pinnedLeftColumnCount,
            pinnedRightColumnCount,
            totalColumnCount,
            parsedColumns,
            headerHeight,
            CellComponent,
            stickyHeaderItemProps,
        ]);

        const groupRowHeight = useMemo(() => {
            if (stickyGroupIndex === null || !groups) {
                const height = size === 'compact' ? 40 : size === 'large' ? 88 : 64;
                return typeof rowHeight === 'number' ? rowHeight : height;
            }

            let cumulativeDataIndex = 0;
            const headerOffset = enableHeader ? 1 : 0;
            for (let i = 0; i < stickyGroupIndex; i++) {
                cumulativeDataIndex += groups[i].itemCount;
            }
            const groupHeaderIndex = headerOffset + cumulativeDataIndex + stickyGroupIndex;

            return getRowHeightWrapper(groupHeaderIndex);
        }, [stickyGroupIndex, groups, getRowHeightWrapper, enableHeader, rowHeight, size]);

        const StickyGroupRow = useMemo(() => {
            if (!shouldRenderStickyGroupRow || stickyGroupIndex === null || !groups) {
                return null;
            }

            const group = groups[stickyGroupIndex];
            const originalData = data.filter((item) => item !== null);
            let cumulativeDataIndex = 0;
            for (let i = 0; i < stickyGroupIndex; i++) {
                cumulativeDataIndex += groups[i].itemCount;
            }

            const groupContent = group.render({
                data: originalData,
                groupIndex: stickyGroupIndex,
                index: 0,
                internalState,
                startDataIndex: cumulativeDataIndex,
            });

            const pinnedLeftWidth = calculatedColumnWidths
                .slice(0, pinnedLeftColumnCount)
                .reduce((sum, width) => sum + width, 0);
            const mainWidth = calculatedColumnWidths
                .slice(pinnedLeftColumnCount, pinnedLeftColumnCount + totalColumnCount)
                .reduce((sum, width) => sum + width, 0);
            const pinnedRightWidth = calculatedColumnWidths
                .slice(pinnedLeftColumnCount + totalColumnCount)
                .reduce((sum, width) => sum + width, 0);

            const totalTableWidth = calculatedColumnWidths.reduce((sum, width) => sum + width, 0);
            const actualStickyTop = stickyGroupTop;

            return (
                <div
                    className={styles.stickyGroupRow}
                    ref={stickyGroupRowRef}
                    style={{
                        top: `${actualStickyTop}px`,
                    }}
                >
                    <div className={styles.stickyGroupRowContent}>
                        {pinnedLeftColumnCount > 0 && (
                            <div
                                className={styles.stickyGroupRowSection}
                                style={{ width: `${pinnedLeftWidth}px` }}
                            >
                                <div
                                    style={{
                                        height: groupRowHeight,
                                        width: `${pinnedLeftWidth}px`,
                                    }}
                                >
                                    {groupContent}
                                </div>
                            </div>
                        )}
                        <div
                            className={styles.stickyGroupRowSection}
                            style={{
                                marginLeft: pinnedLeftColumnCount > 0 ? 0 : '-2rem',
                                marginRight: '-2rem',
                                paddingLeft: pinnedLeftColumnCount > 0 ? 0 : '2rem',
                                paddingRight: '2rem',
                                width: `${mainWidth}px`,
                            }}
                        >
                            <div
                                style={{
                                    height: groupRowHeight,
                                    marginLeft: pinnedLeftWidth > 0 ? `-${pinnedLeftWidth}px` : 0,
                                    width: `${totalTableWidth}px`,
                                }}
                            >
                                {groupContent}
                            </div>
                        </div>
                        {pinnedRightColumnCount > 0 && (
                            <div
                                className={styles.stickyGroupRowSection}
                                style={{ width: `${pinnedRightWidth}px` }}
                            >
                                <div
                                    style={{
                                        height: groupRowHeight,
                                        width: `${pinnedRightWidth}px`,
                                    }}
                                />
                            </div>
                        )}
                    </div>
                </div>
            );
        }, [
            shouldRenderStickyGroupRow,
            stickyGroupIndex,
            groups,
            data,
            internalState,
            calculatedColumnWidths,
            pinnedLeftColumnCount,
            pinnedRightColumnCount,
            totalColumnCount,
            groupRowHeight,
            stickyGroupTop,
        ]);

        return (
            <>
                {StickyHeader}
                {StickyGroupRow}
            </>
        );
    },
);

ItemTableListStickyUI.displayName = 'ItemTableListStickyUI';

const BaseItemTableList = ({
    activeRowId,
    autoFitColumns = false,
    autoScrollToActiveRow = false,
    CellComponent = ItemTableListColumn,
    cellPadding = 'sm',
    columns,
    data,
    enableAlternateRowColors = false,
    enableDrag = true,
    enableDragScroll = true,
    enableEntranceAnimation = true,
    enableExpansion = true,
    enableHeader = true,
    enableHorizontalBorders = false,
    enableRowHoverHighlight = true,
    enableScrollShadow = true,
    enableSelection = true,
    enableStickyGroupRows = false,
    enableStickyHeader = false,
    enableVerticalBorders = false,
    getItem,
    getItemIndex,
    getLoadedItems,
    getRowId,
    groups,
    headerHeight = 40,
    initialTop,
    itemCount,
    itemType,
    onColumnReordered,
    onColumnResized,
    onRangeChanged,
    onScrollEnd,
    overrideControls,
    ref,
    rowHeight,
    size = 'default',
    startRowIndex,
}: ItemTableListProps) => {
    const { playlistId: routePlaylistId } = useParams() as { playlistId?: string };
    const tableId = useId();
    const albumGroupImageSize = useAlbumGroupImageSize();
    const albumGroupItems = useAlbumGroupItems();
    const albumGroupShowFavoriteRating = useAlbumGroupShowFavoriteRating();
    const albumGroupVerticalLayout = useAlbumGroupVerticalLayout();
    const albumGroupMetadataRowCount = useMemo(
        () => albumGroupItems.filter((item) => !item.disabled).length,
        [albumGroupItems],
    );
    const estimatedAlbumGroupContentHeight = useMemo(
        () =>
            estimateAlbumGroupContentHeight({
                metadataRowCount: albumGroupMetadataRowCount,
                showControls: albumGroupShowFavoriteRating,
            }),
        [albumGroupMetadataRowCount, albumGroupShowFavoriteRating],
    );
    const baseItemCount = itemCount ?? data.length;
    const [albumGroupContentHeights, setAlbumGroupContentHeights] = useState(
        () => new Map<string, number>(),
    );

    const setAlbumGroupContentHeight = useCallback((groupKey: string, height: number) => {
        setAlbumGroupContentHeights((prev) => {
            if (prev.get(groupKey) === height) return prev;
            const next = new Map(prev);
            next.set(groupKey, height);
            return next;
        });
    }, []);

    useEffect(() => {
        setAlbumGroupContentHeights(new Map());
    }, [albumGroupShowFavoriteRating, albumGroupVerticalLayout, baseItemCount]);

    const totalItemCount = enableHeader ? baseItemCount + 1 : baseItemCount;
    const [centerContainerWidth, setCenterContainerWidth] = useState(0);
    const [totalContainerWidth, setTotalContainerWidth] = useState(0);

    const columnsForLayout = useMemo(
        () => appendLayoutFillColumn(columns, autoFitColumns),
        [autoFitColumns, columns],
    );

    const {
        calculatedColumnWidths,
        parsedColumns,
        pinnedLeftColumnCount,
        pinnedRightColumnCount,
        totalColumnCount,
    } = useTableColumnModel({
        autoFitColumns,
        centerContainerWidth,
        columns: columnsForLayout,
        totalContainerWidth,
    });

    const { clearColumnResizePreview, columnResizePreview, scheduleColumnResizePreview } =
        useItemTableListColumnResizeLiveState();

    const columnResizeLiveValue = useMemo(
        () => ({
            clearColumnResizePreview,
            scheduleColumnResizePreview,
        }),
        [clearColumnResizePreview, scheduleColumnResizePreview],
    );

    const displayColumnWidths = useMemo(() => {
        if (!columnResizePreview) {
            return calculatedColumnWidths;
        }
        const next = calculatedColumnWidths.slice();
        const { columnIndex, width } = columnResizePreview;
        if (columnIndex >= 0 && columnIndex < next.length) {
            next[columnIndex] = width;
        }
        return next;
    }, [calculatedColumnWidths, columnResizePreview]);

    const playerContext = usePlayer();

    const {
        dataWithGroups: dataWithGroupsFromModel,
        groupHeaderRowCount: groupHeaderRowCountFromModel,
    } = useTableRowModel({
        data,
        enableHeader,
        groups,
    });

    const shouldUseAccessor = typeof getItem === 'function' && typeof itemCount === 'number';

    // Avoid constructing a massive row-model array for infinite lists.
    // Cell renderers use `getRowItem` accessor when provided.
    const dataWithGroups = useMemo<(null | unknown)[]>(() => {
        if (!shouldUseAccessor) return dataWithGroupsFromModel;
        return enableHeader ? [null] : [];
    }, [dataWithGroupsFromModel, enableHeader, shouldUseAccessor]);

    const groupHeaderRowCount = useMemo(() => {
        if (!shouldUseAccessor) return groupHeaderRowCountFromModel;
        return groups?.length ? groups.length : 0;
    }, [groupHeaderRowCountFromModel, groups, shouldUseAccessor]);

    const pinnedRowCount = enableHeader ? 1 : 0;

    // Group headers are inserted at specific indexes, so they add to the total row count
    const totalRowCount = totalItemCount - pinnedRowCount + groupHeaderRowCount;
    const pinnedRowRef = useRef<HTMLDivElement>(null);
    const rowRef = useRef<HTMLDivElement>(null);
    const pinnedLeftColumnRef = useRef<HTMLDivElement>(null);
    const pinnedRightColumnRef = useRef<HTMLDivElement>(null);
    const scrollContainerRef = useRef<HTMLDivElement | null>(null);
    const mergedRowRef = useMergedRef(rowRef, scrollContainerRef);
    const scrollShadowStore = useMemo(() => createTableScrollShadowStore(), []);
    const handleRef = useRef<ItemListHandle | null>(null);
    const { focused, ref: focusRef } = useFocusWithin();
    const containerRef = useRef<HTMLDivElement | null>(null);
    const mergedContainerRef = useMergedRef(containerRef, focusRef);

    useContainerWidthTracking({
        autoFitColumns,
        containerRef,
        rowRef,
        setCenterContainerWidth,
        setTotalContainerWidth,
    });

    const onScrollEndRef = useRef<ItemTableListProps['onScrollEnd']>(onScrollEnd);
    useEffect(() => {
        onScrollEndRef.current = onScrollEnd;
    }, [onScrollEnd]);

    const hasAlbumGroupColumn = useMemo(
        () => parsedColumns.some((col) => col.id === TableColumn.ALBUM_GROUP),
        [parsedColumns],
    );

    const getRowHeight = useCallback(
        (index: number, cellProps: TableItemProps) => {
            const height =
                size === 'compact'
                    ? TableItemSize.COMPACT
                    : size === 'large'
                      ? TableItemSize.LARGE
                      : TableItemSize.DEFAULT;

            const baseHeight =
                typeof rowHeight === 'number' ? rowHeight : rowHeight?.(index, cellProps) || height;

            // If enableHeader is true and this is the first sticky row, use fixed header height
            if (enableHeader && index === 0 && pinnedRowCount > 0) {
                return headerHeight;
            }

            // Grow the group's LAST row when the album image or wrapped album
            // info (title + artists + controls) needs more than the standard
            // combined row height. Other rows keep their standard height.
            if (
                cellProps?.hasAlbumGroupColumn &&
                isLastInAlbumGroup(
                    index,
                    cellProps.getRowItem,
                    cellProps.enableHeader,
                    cellProps.data.length,
                )
            ) {
                const item = cellProps.getRowItem?.(index) as null | undefined | { album?: string };
                if (item?.album) {
                    const groupRowCount = getAlbumGroupRowCount(
                        index,
                        cellProps.getRowItem,
                        cellProps.enableHeader,
                        cellProps.data.length,
                    );
                    const groupStartRowIndex = getAlbumGroupStartRowIndex(
                        index,
                        cellProps.getRowItem,
                        cellProps.enableHeader,
                    );
                    const groupStartItem = cellProps.getRowItem?.(groupStartRowIndex);
                    const groupHeightKey = getAlbumGroupHeightKey(groupStartItem, groupRowCount);
                    const measuredContentHeight = groupHeightKey
                        ? cellProps.albumGroupContentHeights?.get(groupHeightKey)
                        : undefined;
                    // Prefer measured info height once available; otherwise reserve with a
                    // stable estimate so newly virtualized groups do not jump after mount.
                    // Controls-row min-height covers favorites/ratings before the album loads.
                    const contentHeight = measuredContentHeight ?? estimatedAlbumGroupContentHeight;
                    const totalGroupHeight = getAlbumGroupSpanHeight(
                        groupRowCount,
                        baseHeight,
                        albumGroupImageSize,
                        contentHeight,
                        { isVertical: albumGroupVerticalLayout },
                    );
                    const lastRowHeight = totalGroupHeight - (groupRowCount - 1) * baseHeight;
                    if (lastRowHeight > baseHeight) {
                        return lastRowHeight;
                    }
                }
            }

            return baseHeight;
        },
        [
            albumGroupImageSize,
            albumGroupVerticalLayout,
            enableHeader,
            estimatedAlbumGroupContentHeight,
            headerHeight,
            rowHeight,
            pinnedRowCount,
            size,
        ],
    );

    const scrollCellProps = useMemo<TableItemProps>(
        () => ({
            albumGroupContentHeights,
            albumGroupImageSize,
            albumGroupVerticalLayout,
            cellPadding,
            columns: parsedColumns,
            controls: {} as ItemControls,
            data: dataWithGroups,
            enableAlternateRowColors,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            estimatedAlbumGroupContentHeight,
            getRowHeight,
            getRowItem: (rowIndex: number) => {
                if (shouldUseAccessor && getItem) {
                    if (enableHeader && rowIndex === 0) {
                        return null;
                    }

                    const dataIndex = enableHeader ? rowIndex - 1 : rowIndex;
                    return getItem(dataIndex);
                }

                return dataWithGroups[rowIndex];
            },
            hasAlbumGroupColumn,
            internalState: {} as ItemListStateActions,
            itemType,
            playerContext,
            size,
            tableId,
        }),
        [
            albumGroupContentHeights,
            albumGroupImageSize,
            albumGroupVerticalLayout,
            cellPadding,
            dataWithGroups,
            enableAlternateRowColors,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            estimatedAlbumGroupContentHeight,
            getItem,
            getRowHeight,
            hasAlbumGroupColumn,
            itemType,
            parsedColumns,
            playerContext,
            shouldUseAccessor,
            size,
            tableId,
        ],
    );

    const {
        calculateScrollTopForIndex,
        getRowHeightAtIndex,
        scrollToTableIndex,
        scrollToTableOffset,
    } = useTableScrollToIndex({
        albumGroupContentHeights,
        autoScrollToActiveRow,
        enableHeader,
        getRowHeight,
        hasAlbumGroupColumn,
        pinnedLeftColumnRef,
        pinnedRightColumnRef,
        pinnedRowCount,
        rowRef,
        scrollCellProps,
    });

    const scrollSyncKey = useMemo(
        () =>
            parsedColumns
                .map(
                    (col) =>
                        `${col.id}:${col.pinned ?? 'none'}:${col.width}:${col.isEnabled !== false}`,
                )
                .join('|'),
        [parsedColumns],
    );

    useTablePaneSync({
        enableDrag,
        enableDragScroll,
        handleRef,
        onScrollEndRef,
        pinnedLeftColumnCount,
        pinnedLeftColumnRef,
        pinnedRightColumnCount,
        pinnedRightColumnRef,
        pinnedRowRef,
        rowRef,
        scrollContainerRef,
        scrollShadowStore,
        scrollSyncKey,
    });

    // Create a wrapper for getRowHeight that doesn't require cellProps (for sticky group rows hook)
    const getRowHeightWrapper = useCallback(
        (index: number) => {
            const height =
                size === 'compact'
                    ? TableItemSize.COMPACT
                    : size === 'large'
                      ? TableItemSize.LARGE
                      : TableItemSize.DEFAULT;

            const baseHeight = typeof rowHeight === 'number' ? rowHeight : height;

            // If enableHeader is true and this is the first sticky row, use fixed header height
            if (enableHeader && index === 0 && pinnedRowCount > 0) {
                return headerHeight;
            }

            return baseHeight;
        },
        [enableHeader, headerHeight, rowHeight, pinnedRowCount, size],
    );

    const dataRef = useRef(data);
    const getLoadedItemsRef = useRef(getLoadedItems);
    dataRef.current = data;
    getLoadedItemsRef.current = getLoadedItems;

    const getDataFn = useCallback(() => {
        const loadedItems = getLoadedItemsRef.current?.();
        if (loadedItems?.length) {
            return loadedItems;
        }
        return dataRef.current ?? [];
    }, []);

    const extractRowId = useMemo(() => createExtractRowId(getRowId), [getRowId]);

    const internalState = useItemListState(getDataFn, extractRowId);

    const getStateItem = useCallback(
        (item: any): ItemListStateItemWithRequiredProperties | null => {
            if (!hasRequiredItemProperties(item)) {
                return null;
            }
            if (
                typeof item === 'object' &&
                item !== null &&
                '_serverId' in item &&
                '_itemType' in item
            ) {
                return item as ItemListStateItemWithRequiredProperties;
            }
            return null;
        },
        [],
    );

    const { handleKeyDown } = useTableKeyboardNavigation({
        calculateScrollTopForIndex,
        data,
        enableHeader,
        enableSelection,
        extractRowId,
        getItem,
        getItemIndex,
        getRowHeightAtIndex,
        getStateItem,
        hasRequiredStateItemProperties,
        internalState,
        itemCount: baseItemCount,
        pinnedRightColumnCount,
        pinnedRightColumnRef,
        rowRef,
        scrollToTableIndex,
    });

    useTableInitialScroll({
        initialTop,
        scrollToTableIndex,
        scrollToTableOffset,
        startRowIndex,
    });

    useTableImperativeHandle({
        autoScrollToActiveRow,
        enableHeader,
        handleRef,
        internalState,
        ref,
        scrollToTableIndex,
        scrollToTableOffset,
    });

    const controls = useDefaultItemListControls({
        onColumnReordered,
        onColumnResized,
        overrides: overrideControls,
    });

    // Create itemProps for sticky header
    const stickyHeaderItemProps: TableItemProps = useMemo(
        () => ({
            calculatedColumnWidths: displayColumnWidths,
            cellPadding,
            columns: parsedColumns,
            controls,
            data: [null], // Header row
            enableAlternateRowColors,
            enableColumnReorder: !!onColumnReordered,
            enableColumnResize: !!onColumnResized,
            enableDrag,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            getRowHeight,
            groups,
            internalState,
            itemType,
            pinnedLeftColumnCount,
            pinnedLeftColumnWidths: displayColumnWidths.slice(0, pinnedLeftColumnCount),
            pinnedRightColumnCount,
            pinnedRightColumnWidths: displayColumnWidths.slice(
                pinnedLeftColumnCount + totalColumnCount,
            ),
            playerContext,
            playlistId: routePlaylistId,
            size,
            tableId,
        }),
        [
            displayColumnWidths,
            cellPadding,
            controls,
            parsedColumns,
            enableAlternateRowColors,
            enableDrag,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            getRowHeight,
            groups,
            internalState,
            itemType,
            onColumnReordered,
            onColumnResized,
            pinnedLeftColumnCount,
            pinnedRightColumnCount,
            playerContext,
            routePlaylistId,
            size,
            tableId,
            totalColumnCount,
        ],
    );

    const onShowPlayingSong = useCallback(() => {
        const targetId = usePlayerStore.getState().getCurrentSong()?.id;
        if (!targetId) return;
        const index =
            getItemIndex?.(targetId) ??
            data.findIndex((item) => (item as null | { id?: string })?.id === targetId);
        if (index === undefined || index < 0) return;
        handleRef.current?.scrollToIndex(index, { align: 'center', behavior: 'auto' });
    }, [data, getItemIndex]);

    useListHotkeys({
        controls,
        focusContainerRef: containerRef,
        focused,
        internalState,
        itemType,
        onShowPlayingSong,
    });

    const tableConfigValue = useMemo<ItemTableListConfig>(
        () => ({
            cellPadding,
            columns: parsedColumns,
            controls,
            enableAlternateRowColors,
            enableColumnReorder: !!onColumnReordered,
            enableColumnResize: !!onColumnResized,
            enableDrag,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            getRowHeight,
            groups,
            internalState,
            itemType,
            playerContext,
            playlistId: routePlaylistId,
            size,
            startRowIndex,
            tableId,
        }),
        [
            cellPadding,
            parsedColumns,
            controls,
            enableAlternateRowColors,
            onColumnReordered,
            onColumnResized,
            enableDrag,
            enableExpansion,
            enableHeader,
            enableHorizontalBorders,
            enableRowHoverHighlight,
            enableSelection,
            enableVerticalBorders,
            getRowHeight,
            groups,
            internalState,
            itemType,
            playerContext,
            routePlaylistId,
            size,
            startRowIndex,
            tableId,
        ],
    );

    const columnCellComponents = useColumnCellComponents(
        parsedColumns.map((c) => c.id as TableColumn),
        itemType,
    );

    const optimizedCellComponent = useMemo<
        JSXElementConstructor<CellComponentProps<TableItemProps>>
    >(() => {
        if (CellComponent && CellComponent !== ItemTableListColumn) {
            return CellComponent;
        }

        return (cellProps: CellComponentProps<TableItemProps>) => {
            return (
                <MemoizedCellRouter {...cellProps} columnCellComponents={columnCellComponents} />
            );
        };
    }, [CellComponent, columnCellComponents]);

    const tableMotion = (
        <motion.div
            className={styles.itemTableListContainer}
            onKeyDown={handleKeyDown}
            onMouseDown={(e) => {
                const element = e.currentTarget as HTMLDivElement;
                // Focus without scrolling into view
                if (element.focus) {
                    element.focus({ preventScroll: true });
                }
            }}
            ref={mergedContainerRef}
            tabIndex={0}
            {...animationProps.fadeIn}
            transition={{ duration: enableEntranceAnimation ? 0.3 : 0, ease: 'anticipate' }}
        >
            <ItemTableListStickyUI
                calculatedColumnWidths={displayColumnWidths}
                CellComponent={optimizedCellComponent}
                containerRef={containerRef}
                data={data}
                enableHeader={!!enableHeader}
                enableStickyGroupRows={!!enableStickyGroupRows}
                enableStickyHeader={!!enableStickyHeader}
                getRowHeightWrapper={getRowHeightWrapper}
                groups={groups}
                headerHeight={headerHeight}
                internalState={internalState}
                parsedColumns={parsedColumns}
                pinnedLeftColumnCount={pinnedLeftColumnCount}
                pinnedLeftColumnRef={pinnedLeftColumnRef}
                pinnedRightColumnCount={pinnedRightColumnCount}
                pinnedRightColumnRef={pinnedRightColumnRef}
                pinnedRowRef={pinnedRowRef}
                rowHeight={rowHeight}
                rowRef={rowRef}
                size={size}
                stickyHeaderItemProps={stickyHeaderItemProps}
                totalColumnCount={totalColumnCount}
            />
            <MemoizedVirtualizedTableGrid
                albumGroupContentHeights={albumGroupContentHeights}
                calculatedColumnWidths={displayColumnWidths}
                CellComponent={optimizedCellComponent}
                data={data}
                dataWithGroups={dataWithGroups}
                enableScrollShadow={enableScrollShadow}
                estimatedAlbumGroupContentHeight={estimatedAlbumGroupContentHeight}
                getItem={getItem}
                headerHeight={headerHeight}
                mergedRowRef={mergedRowRef}
                onRangeChanged={onRangeChanged}
                parsedColumns={parsedColumns}
                pinnedLeftColumnCount={pinnedLeftColumnCount}
                pinnedLeftColumnRef={pinnedLeftColumnRef}
                pinnedRightColumnCount={pinnedRightColumnCount}
                pinnedRightColumnRef={pinnedRightColumnRef}
                pinnedRowCount={pinnedRowCount}
                pinnedRowRef={pinnedRowRef}
                scrollShadowStore={scrollShadowStore}
                setAlbumGroupContentHeight={setAlbumGroupContentHeight}
                tableConfig={tableConfigValue}
                totalColumnCount={totalColumnCount}
                totalRowCount={totalRowCount}
            />
        </motion.div>
    );

    return (
        <ItemTableListStoreProvider activeRowId={activeRowId}>
            <ItemTableListConfigProvider value={tableConfigValue}>
                {onColumnResized ? (
                    <ItemTableListColumnResizeLiveProvider value={columnResizeLiveValue}>
                        {tableMotion}
                    </ItemTableListColumnResizeLiveProvider>
                ) : (
                    tableMotion
                )}
            </ItemTableListConfigProvider>
        </ItemTableListStoreProvider>
    );
};

export const ItemTableList = memo(BaseItemTableList);

ItemTableList.displayName = 'ItemTableList';
