import { useMemo, useState } from 'react';

interface PaginatedData<T> {
    data: T[];
    page: number;
    pageSize: number;
    paginated: boolean;
    totalCount: number;
    paginationVariant: 'expanded' | 'compact';
    onPageChange: (nextPage: number) => void;
    onPageSizeChange: (newPageSize: number) => void;
}

interface PaginationOptions<T> {
    variant?: 'expanded' | 'compact';
    pageSize?: number;
    alwaysVisible?: boolean;
    indexByColumn?: keyof T;
}

export const useTablePagination = <T,>(
    tableData: T[] = [],
    options?: PaginationOptions<T>
): PaginatedData<T> => {
    const {
        variant = 'compact',
        indexByColumn,
        alwaysVisible = false,
        pageSize: defaultPageSize = 20,
    } = options || {};

    const [page, setPage] = useState(0);
    const [pageSize, setPageSize] = useState(defaultPageSize);

    const paginatedData = useMemo(() => {
        if (tableData.length === 0) return [];

        const pageStart = page * pageSize;
        const pageEnd = pageStart + pageSize;

        if (indexByColumn) {
            // Find new page start/end based on the index column
            const pageRange = tableData.reduce((range, item, index) => {
                if (range.length < 1 && item[indexByColumn] === pageStart + 1)
                    range[0] = index;
                if (range.length === 1 && item[indexByColumn] === pageEnd)
                    range[1] = index + 1;

                return range;
            }, [] as number[]);

            return tableData.slice(pageRange[0], pageRange[1]);
        }

        return tableData.slice(pageStart, pageEnd);
    }, [tableData, page, pageSize, indexByColumn]);

    const onPageChange = (nextPage: number) => {
        setPage(nextPage);
    };

    const onPageSizeChange = (newPageSize: number) => {
        setPageSize(newPageSize);
    };

    const totalCount = indexByColumn
        ? Number(tableData[tableData.length - 1][indexByColumn])
        : tableData.length;
    const paginated = alwaysVisible || totalCount > defaultPageSize;

    return {
        page,
        pageSize,
        paginated,
        totalCount,
        onPageChange,
        onPageSizeChange,
        data: paginatedData,
        paginationVariant: variant,
    };
};
