import {useEffect} from '@wordpress/element';

/**
 * Custom hook to isolate scroll events from external scroll libraries
 *
 * This hook prevents custom scroll libraries from hijacking scroll events within the chatbot
 * by stopping event propagation and preventing scroll chaining.
 *
 * @param {React.RefObject} ref - Reference to the scrollable element
 * @param {boolean} enabled - Whether the scroll isolation is enabled (default: true)
 */
const useScrollIsolation = (ref, enabled = true) => {
    useEffect(() => {
        if (!enabled) {
            return;
        }

        const element = ref?.current;
        if (!element) {
            return;
        }

        /**
         * Handle wheel events (mouse wheel, trackpad)
         */
        const handleWheel = (e) => {
            const {scrollTop, scrollHeight, clientHeight} = element;
            const isScrollingDown = e.deltaY > 0;
            const isScrollingUp = e.deltaY < 0;

            // Check if we're at the boundaries
            const isAtTop = scrollTop === 0;
            const isAtBottom = scrollTop + clientHeight >= scrollHeight - 1;

            // Prevent scroll chaining at boundaries
            if ((isAtTop && isScrollingUp) || (isAtBottom && isScrollingDown)) {
                e.preventDefault();
                e.stopPropagation();
                return;
            }

            // Stop propagation to prevent external scroll libraries from capturing the event
            e.stopPropagation();
        };

        /**
         * Handle touch events (mobile, tablet)
         */
        let touchStartY = 0;
        let touchStartX = 0;

        const handleTouchStart = (e) => {
            touchStartY = e.touches[0].clientY;
            touchStartX = e.touches[0].clientX;
            // Stop propagation to prevent external scroll libraries
            e.stopPropagation();
        };

        const handleTouchMove = (e) => {
            if (!touchStartY) {
                return;
            }

            const touchEndY = e.touches[0].clientY;
            const touchEndX = e.touches[0].clientX;
            const deltaY = touchStartY - touchEndY;
            const deltaX = touchStartX - touchEndX;

            // Determine if it's a vertical scroll
            const isVerticalScroll = Math.abs(deltaY) > Math.abs(deltaX);

            if (isVerticalScroll) {
                const {scrollTop, scrollHeight, clientHeight} = element;
                const isScrollingDown = deltaY > 0;
                const isScrollingUp = deltaY < 0;

                // Check if we're at the boundaries
                const isAtTop = scrollTop === 0;
                const isAtBottom = scrollTop + clientHeight >= scrollHeight - 1;

                // Prevent scroll chaining at boundaries
                if ((isAtTop && isScrollingUp) || (isAtBottom && isScrollingDown)) {
                    e.preventDefault();
                    e.stopPropagation();
                    return;
                }
            }

            // Stop propagation to prevent external scroll libraries
            e.stopPropagation();
        };

        const handleTouchEnd = () => {
            touchStartY = 0;
            touchStartX = 0;
        };

        /**
         * Handle pointer events (unified for mouse/touch/pen)
         */
        const handlePointerDown = (e) => {
            e.stopPropagation();
        };

        const handlePointerMove = (e) => {
            // Only stop propagation if we're actually scrolling
            if (e.buttons > 0) {
                e.stopPropagation();
            }
        };

        /**
         * Prevent external scroll libraries from affecting this element
         */
        const preventExternalScroll = (e) => {
            e.stopImmediatePropagation();
        };

        // Add event listeners with capture phase to intercept before external libraries
        element.addEventListener('wheel', handleWheel, {passive: false, capture: true});
        element.addEventListener('touchstart', handleTouchStart, {passive: false, capture: true});
        element.addEventListener('touchmove', handleTouchMove, {passive: false, capture: true});
        element.addEventListener('touchend', handleTouchEnd, {passive: true, capture: true});
        element.addEventListener('pointerdown', handlePointerDown, {passive: true, capture: true});
        element.addEventListener('pointermove', handlePointerMove, {passive: true, capture: true});

        // Additional listeners for scroll event itself
        element.addEventListener('scroll', preventExternalScroll, {passive: true, capture: true});

        // Mark element to be ignored by common scroll libraries
        element.setAttribute('data-scroll-lock', 'true');
        element.setAttribute('data-lenis-prevent', 'true');
        element.setAttribute('data-locomotive-scroll-prevent', 'true');

        // Cleanup
        return () => {
            element.removeEventListener('wheel', handleWheel, {capture: true});
            element.removeEventListener('touchstart', handleTouchStart, {capture: true});
            element.removeEventListener('touchmove', handleTouchMove, {capture: true});
            element.removeEventListener('touchend', handleTouchEnd, {capture: true});
            element.removeEventListener('pointerdown', handlePointerDown, {capture: true});
            element.removeEventListener('pointermove', handlePointerMove, {capture: true});
            element.removeEventListener('scroll', preventExternalScroll, {capture: true});

            element.removeAttribute('data-scroll-lock');
            element.removeAttribute('data-lenis-prevent');
            element.removeAttribute('data-locomotive-scroll-prevent');
        };
    }, [ref, enabled]);
};

export default useScrollIsolation;

