import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import classNames from 'classnames';
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Icon, IconButton } from '../../basic';
import './styles.scss';
const DRAG_THRESHOLD_PX = 6;
export default function AppPagination({ totalElements, pagination, setPagination, hideItensPage, numItens = [10, 25, 50], size = 'medium', }) {
    const { t } = useTranslation('common');
    const scrollContainerRef = useRef(null);
    const activePageButtonRef = useRef(null);
    const [stripScrollEdges, setStripScrollEdges] = useState({
        overflow: false,
        canScrollLeft: false,
        canScrollRight: false,
    });
    const { isDraggingScroll, suppressPageClickRef, pagesTotalPointerHandlers } = useDragToScrollRow(scrollContainerRef, DRAG_THRESHOLD_PX);
    const updateStripScrollEdgeState = useCallback(() => {
        const el = scrollContainerRef.current;
        if (!el)
            return;
        const maxScroll = el.scrollWidth - el.clientWidth;
        const overflow = maxScroll > 1;
        setStripScrollEdges({
            overflow,
            canScrollLeft: overflow && el.scrollLeft > 1,
            canScrollRight: overflow && el.scrollLeft < maxScroll - 1,
        });
    }, []);
    const scrollPageStrip = useCallback((direction) => {
        const el = scrollContainerRef.current;
        if (!el)
            return;
        const step = Math.max(72, Math.floor(el.clientWidth * 0.8));
        el.scrollBy({ left: direction * step, behavior: 'smooth' });
    }, []);
    const numPages = Math.ceil(totalElements / pagination.pageSize);
    const currentPage = pagination.pageIndex + 1;
    const getFirstElementNumber = () => pagination.pageIndex * pagination.pageSize + 1;
    const getLastElementNumber = () => Math.min((pagination.pageIndex + 1) * pagination.pageSize, totalElements);
    const setPageSize = (p) => {
        setPagination({ ...pagination, pageSize: p });
    };
    const setPageIndex = (p) => {
        setPagination({ ...pagination, pageIndex: p });
    };
    /** Scroll only the page strip — never `scrollIntoView`, which can scroll the document. */
    const scrollActivePageIntoCenter = useCallback(() => {
        const container = scrollContainerRef.current;
        const button = activePageButtonRef.current;
        if (!container || !button)
            return;
        const maxScroll = Math.max(0, container.scrollWidth - container.clientWidth);
        if (maxScroll <= 0)
            return;
        const cRect = container.getBoundingClientRect();
        const bRect = button.getBoundingClientRect();
        const buttonLeftInContent = container.scrollLeft + (bRect.left - cRect.left);
        const targetScrollLeft = buttonLeftInContent - container.clientWidth / 2 + button.offsetWidth / 2;
        const clamped = Math.max(0, Math.min(maxScroll, targetScrollLeft));
        container.scrollTo({ left: clamped, behavior: 'smooth' });
    }, []);
    useLayoutEffect(() => {
        scrollActivePageIntoCenter();
        requestAnimationFrame(() => updateStripScrollEdgeState());
    }, [
        numPages,
        pagination.pageIndex,
        pagination.pageSize,
        scrollActivePageIntoCenter,
        updateStripScrollEdgeState,
    ]);
    useEffect(() => {
        const el = scrollContainerRef.current;
        if (!el)
            return;
        const onScroll = () => updateStripScrollEdgeState();
        el.addEventListener('scroll', onScroll, { passive: true });
        const ro = new ResizeObserver(() => updateStripScrollEdgeState());
        ro.observe(el);
        return () => {
            el.removeEventListener('scroll', onScroll);
            ro.disconnect();
        };
    }, [updateStripScrollEdgeState]);
    useEffect(() => {
        const el = scrollContainerRef.current;
        if (!el)
            return;
        const onWheel = (e) => {
            if (el.scrollWidth <= el.clientWidth + 1)
                return;
            const dominantX = Math.abs(e.deltaX) > Math.abs(e.deltaY);
            const scrollDelta = dominantX ? e.deltaX : e.deltaY;
            if (scrollDelta === 0)
                return;
            const maxScroll = el.scrollWidth - el.clientWidth;
            const nextLeft = el.scrollLeft + scrollDelta;
            const clamped = Math.max(0, Math.min(maxScroll, nextLeft));
            const atStart = el.scrollLeft <= 0;
            const atEnd = el.scrollLeft >= maxScroll - 1;
            if ((scrollDelta < 0 && atStart) || (scrollDelta > 0 && atEnd)) {
                return;
            }
            el.scrollLeft = clamped;
            e.preventDefault();
        };
        el.addEventListener('wheel', onWheel, { passive: false });
        return () => el.removeEventListener('wheel', onWheel);
    }, []);
    return (_jsxs("div", { className: classNames('app-table-pagination', {
            small: size === 'small',
        }), children: [_jsxs("div", { className: "itens-container", children: [!hideItensPage && (_jsxs("div", { className: "itens-page", children: [_jsx("span", { className: "itens-page-label", children: t('table.label.rows-page') }), _jsx("select", { className: "select-pages", value: pagination.pageSize, onChange: (e) => setPageSize(Number(e.target.value)), children: numItens.map((pageSizeOption) => (_jsx("option", { value: pageSizeOption, children: pageSizeOption }, pageSizeOption))) })] })), _jsx("div", { className: "itens-total", children: _jsx("span", { children: _jsx(Trans, { t: t, i18nKey: "table.label.items", values: {
                                    first: getFirstElementNumber(),
                                    last: getLastElementNumber(),
                                    total: totalElements,
                                } }) }) })] }), _jsxs("div", { className: "pages-navigation", children: [_jsx(IconButton, { size: size, mode: "tonal", onClick: () => setPageIndex(pagination.pageIndex - 1), disabled: pagination.pageIndex === 0, name: "chevron_backward" }), stripScrollEdges.overflow && (_jsx("button", { type: "button", className: "page-strip-nudge", disabled: !stripScrollEdges.canScrollLeft, onClick: () => scrollPageStrip(-1), "aria-label": t('table.pagination.scroll-strip-left'), title: t('table.pagination.scroll-strip-left'), children: _jsx(Icon, { name: "keyboard_double_arrow_left", size: "x-small" }) })), _jsx("div", { ref: scrollContainerRef, className: classNames('pages-total', {
                            'is-dragging': isDraggingScroll,
                        }), ...pagesTotalPointerHandlers, children: Array.from({ length: numPages }, (_, index) => {
                            const pageNum = index + 1;
                            const isActive = pageNum === currentPage;
                            return (_jsx("button", { ref: isActive ? activePageButtonRef : undefined, type: "button", className: classNames('page-number', { active: isActive }), onClick: () => {
                                    if (suppressPageClickRef.current) {
                                        return;
                                    }
                                    setPageIndex(index);
                                }, "aria-current": isActive ? 'page' : undefined, children: pageNum }, pageNum));
                        }) }), _jsx("div", { className: "pages-total-mobile", children: _jsx("select", { className: "select-pages", value: currentPage, onChange: (e) => setPageIndex(Number(e.target.value) - 1), children: Array.from({ length: numPages }, (_, index) => (_jsx("option", { value: index + 1, children: index + 1 }, index + 1))) }) }), stripScrollEdges.overflow && (_jsx("button", { type: "button", className: "page-strip-nudge", disabled: !stripScrollEdges.canScrollRight, onClick: () => scrollPageStrip(1), "aria-label": t('table.pagination.scroll-strip-right'), title: t('table.pagination.scroll-strip-right'), children: _jsx(Icon, { name: "keyboard_double_arrow_right", size: "x-small" }) })), _jsx(IconButton, { size: size, mode: "tonal", onClick: () => setPageIndex(pagination.pageIndex + 1), disabled: pagination.pageIndex >= numPages - 1, name: "chevron_forward" })] })] }));
}
const initialDragRow = {
    pointerId: null,
    startX: 0,
    startScrollLeft: 0,
    dragging: false,
};
/**
 * Horizontal drag-to-scroll for an overflow-x container: hides reliance on
 * the scrollbar (paired with CSS) while keeping click-vs-drag distinct.
 */
function useDragToScrollRow(containerRef, dragThresholdPx) {
    const suppressPageClickRef = useRef(false);
    const dragRef = useRef({ ...initialDragRow });
    const [isDraggingScroll, setIsDraggingScroll] = useState(false);
    const pagesTotalPointerHandlers = useMemo(() => {
        const endPointer = (e) => {
            const d = dragRef.current;
            if (d.pointerId !== e.pointerId)
                return;
            const el = containerRef.current;
            if (d.dragging) {
                suppressPageClickRef.current = true;
                window.setTimeout(() => {
                    suppressPageClickRef.current = false;
                }, 0);
            }
            dragRef.current = { ...initialDragRow };
            setIsDraggingScroll(false);
            if (el) {
                try {
                    el.releasePointerCapture(e.pointerId);
                }
                catch {
                    /* capture may already be released */
                }
            }
        };
        return {
            onPointerDown(e) {
                if (e.button !== 0)
                    return;
                const target = e.target;
                if (target?.closest('.page-number')) {
                    return;
                }
                const el = containerRef.current;
                if (!el)
                    return;
                dragRef.current = {
                    pointerId: e.pointerId,
                    startX: e.clientX,
                    startScrollLeft: el.scrollLeft,
                    dragging: false,
                };
                el.setPointerCapture(e.pointerId);
            },
            onPointerMove(e) {
                const d = dragRef.current;
                if (d.pointerId !== e.pointerId)
                    return;
                const el = containerRef.current;
                if (!el)
                    return;
                const dx = e.clientX - d.startX;
                if (!d.dragging && Math.abs(dx) > dragThresholdPx) {
                    d.dragging = true;
                    setIsDraggingScroll(true);
                }
                if (d.dragging) {
                    el.scrollLeft = d.startScrollLeft - dx;
                    e.preventDefault();
                }
            },
            onPointerUp: endPointer,
            onPointerCancel: endPointer,
        };
    }, [containerRef, dragThresholdPx]);
    return {
        isDraggingScroll,
        suppressPageClickRef,
        pagesTotalPointerHandlers,
    };
}
