import { Table } from '@tanstack/react-table';

import { Button } from '@/components/ui/button';
import { PaginatedData } from '@/types';
import { router } from '@inertiajs/react';

const PER_PAGE_OPTIONS = [10, 15, 20, 25, 30, 40, 50, 100];

interface DataTablePaginationProps<TData> {
    table: Table<TData>;
    paginatedData: PaginatedData<TData>;
    navigate?: (params: Record<string, any>) => void;
}

export function DataTablePagination<TData>({ table, paginatedData, navigate }: DataTablePaginationProps<TData>) {
    const { meta, links, queryParams } = paginatedData || {};

    // If no pagination data, don't render anything
    if (!meta || !links) {
        return null;
    }

    // Per page change
    const handlePerPageChange = (value: number) => {
        const nextParams = { ...queryParams, per_page: value, page: 1 };

        if (navigate) {
            navigate(nextParams);
            syncUrlQuery(nextParams);
        } else {
            router.get(
                route(route().current() ?? ''),
                {
                    ...nextParams,
                },
                {
                    preserveScroll: true,
                },
            );
        }
    };

    const syncUrlQuery = (params: Record<string, any>) => {
        const url = new URL(window.location.href);
        const searchParams = new URLSearchParams();

        Object.entries(params).forEach(([key, value]) => {
            if (value === undefined || value === null || value === '') {
                return;
            }

            if (Array.isArray(value)) {
                value.filter((item) => item !== undefined && item !== null && item !== '').forEach((item) => searchParams.append(key, String(item)));
                return;
            }

            searchParams.set(key, String(value));
        });

        const qs = searchParams.toString();
        const nextUrl = `${url.pathname}${qs ? `?${qs}` : ''}${url.hash}`;
        window.history.pushState({}, '', nextUrl);
    };

    const goToPage = (page: number) => {
        if (page < 1 || page > meta.last_page) return;

        const nextParams = { ...queryParams, page };

        if (navigate) {
            navigate(nextParams);
            syncUrlQuery(nextParams);
        } else {
            router.get(route(route().current() ?? ''), nextParams, { preserveState: true, preserveScroll: true });
        }
    };

    const maxVisiblePages = 5;
    const halfWindow = Math.floor(maxVisiblePages / 2);

    let startPage = Math.max(1, meta.current_page - halfWindow);
    let endPage = startPage + maxVisiblePages - 1;

    if (endPage > meta.last_page) {
        endPage = meta.last_page;
        startPage = Math.max(1, endPage - maxVisiblePages + 1);
    }

    const visiblePages = Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);

    return (
        <div className="flex items-center justify-between">
            <div className="hidden text-sm text-primary/80 md:block">
                Showing {meta.from} to {meta.to} of {meta.total} results
            </div>
            <div className="flex items-center space-x-2">
                <Button
                    variant="outline"
                    size="sm"
                    onClick={() => {
                        if (links.prev === null || meta.current_page === 1) return;
                        if (navigate) {
                            navigate({ ...queryParams, page: meta.current_page - 1 });
                        } else {
                            router.get(
                                route(route().current() ?? ''),
                                { ...queryParams, page: meta.current_page - 1 },
                                { preserveState: true, preserveScroll: true },
                            );
                        }
                    }}
                    disabled={links.prev === null || meta.current_page === 1}
                >
                    Previous
                </Button>

                {/* Page Numbers */}
                <div className="flex items-center space-x-1 text-primary">
                    {startPage > 1 && (
                        <>
                            <Button variant="outline" size="sm" onClick={() => goToPage(1)}>
                                1
                            </Button>
                            {startPage > 2 && <span className="px-2 text-primary">...</span>}
                        </>
                    )}

                    {visiblePages.map((page) => {
                        return (
                            <Button
                                key={page}
                                variant={page === meta.current_page ? 'default' : 'outline'}
                                size="sm"
                                className={`${page === meta.current_page && 'bg-success text-white hover:bg-brand-800'} h-8 w-8`}
                                onClick={() => goToPage(page)}
                            >
                                {page}
                            </Button>
                        );
                    })}

                    {endPage < meta.last_page && (
                        <>
                            {endPage < meta.last_page - 1 && <span className="px-2 text-primary">...</span>}
                            <Button variant="outline" size="sm" onClick={() => goToPage(meta.last_page)}>
                                {meta.last_page}
                            </Button>
                        </>
                    )}
                </div>

                <Button
                    variant="outline"
                    size="sm"
                    onClick={() => {
                        if (links.next === null || meta.current_page === meta.last_page) return;
                        goToPage(meta.current_page + 1);
                    }}
                    disabled={links.next === null || meta.current_page === meta.last_page}
                >
                    Next
                </Button>
            </div>
        </div>
    );
}
