import { useCallback, useEffect, useState } from 'react';
import type { InertiaPaginatorSlice } from '@/components/inertia-paginator-footer';

type PaginatedAuditResponse<T> = InertiaPaginatorSlice & {
    data: T[];
    [key: string]: unknown;
};

function paginatorFromResponse<T>(json: PaginatedAuditResponse<T>): InertiaPaginatorSlice {
    return {
        current_page: json.current_page,
        last_page: json.last_page,
        total: json.total,
        from: json.from,
        to: json.to,
        prev_page_url: json.prev_page_url,
        next_page_url: json.next_page_url,
    };
}

export function usePaginatedAuditSection<T>(url: string) {
    const [page, setPage] = useState(1);
    const [data, setData] = useState<T[]>([]);
    const [paginator, setPaginator] = useState<InertiaPaginatorSlice | null>(null);
    const [meta, setMeta] = useState<Record<string, unknown>>({});
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);
    const [reloadToken, setReloadToken] = useState(0);

    const loadPage = useCallback(
        async (pageNum: number, signal?: AbortSignal) => {
            setLoading(true);
            setError(null);

            try {
                const response = await fetch(`${url}?page=${pageNum}`, {
                    headers: { Accept: 'application/json' },
                    credentials: 'same-origin',
                    signal,
                });

                if (!response.ok) {
                    throw new Error('fetch failed');
                }

                const json = (await response.json()) as PaginatedAuditResponse<T>;
                const { data: rows, ...rest } = json;

                setData(rows);
                setPaginator(paginatorFromResponse(json));
                setMeta(rest);
                setLoading(false);
            } catch (cause) {
                if (cause instanceof DOMException && cause.name === 'AbortError') {
                    return;
                }

                setData([]);
                setPaginator(null);
                setMeta({});
                setError('No se pudo cargar esta sección.');
                setLoading(false);
            }
        },
        [url],
    );

    useEffect(() => {
        const controller = new AbortController();
        void loadPage(page, controller.signal);

        return () => controller.abort();
    }, [page, loadPage, reloadToken]);

    const reload = useCallback(() => {
        setReloadToken((token) => token + 1);
    }, []);

    return {
        data,
        paginator,
        meta,
        loading,
        error,
        page,
        setPage,
        reload,
    };
}
