"use client";

import { useCallback, useEffect, useRef, useState } from "react";

export function useScrollToBottom() {
	const containerRef = useRef(null);
	const [showScrollButton, setShowScrollButton] = useState(false);
	const [shouldAutoScroll, setShouldAutoScroll] = useState(true);
	const isUserScrolling = useRef(false);
	const isGrowing = useRef(false);

	const getViewport = useCallback((element) => {
		return element?.closest("[data-radix-scroll-area-viewport]");
	}, []);

	const isAtBottom = useCallback((viewport) => {
		const { scrollTop, scrollHeight, clientHeight } = viewport;
		return Math.abs(scrollHeight - scrollTop - clientHeight) < 10;
	}, []);

	const updateScrollState = useCallback((viewport) => {
        const { scrollHeight, clientHeight } = viewport;
        const hasScrollableContent = scrollHeight > clientHeight;
        const atBottom = isAtBottom(viewport);

        setShowScrollButton(hasScrollableContent && !atBottom);

        if (!isUserScrolling.current) {
            setShouldAutoScroll(atBottom);
        }
    }, [isAtBottom]);

	useEffect(() => {
		const container = containerRef.current;
		const viewport = getViewport(container);

		if (!container || !viewport) {
			return;
		}

		updateScrollState(viewport);

		const handleScroll = () => {
			if (!isUserScrolling.current) {
				updateScrollState(viewport);
			}
		};

		const handleTouchStart = () => {
			isUserScrolling.current = true;
		};

		const handleTouchEnd = () => {
			isUserScrolling.current = false;
			updateScrollState(viewport);
		};

		let growthTimeout;
		const observer = new MutationObserver(() => {
			isGrowing.current = true;
			window.clearTimeout(growthTimeout);

			if (shouldAutoScroll && !isUserScrolling.current) {
				viewport.scrollTo({
					top: viewport.scrollHeight,

					behavior: "instant",
				});
			}
			updateScrollState(viewport);

			growthTimeout = window.setTimeout(() => {
				isGrowing.current = false;
			}, 100);
		});

		viewport.addEventListener("scroll", handleScroll, { passive: true });
		viewport.addEventListener("touchstart", handleTouchStart);
		viewport.addEventListener("touchend", handleTouchEnd);

		observer.observe(container, {
			childList: true,
			subtree: true,
			attributes: true,
			characterData: true,
		});

		return () => {
			window.clearTimeout(growthTimeout);
			observer.disconnect();
			viewport.removeEventListener("scroll", handleScroll);
			viewport.removeEventListener("touchstart", handleTouchStart);
			viewport.removeEventListener("touchend", handleTouchEnd);
		};
	}, [getViewport, updateScrollState, shouldAutoScroll]);

	const scrollToBottom = () => {
		const viewport = getViewport(containerRef.current);
		if (!viewport) {
			return;
		}

		setShouldAutoScroll(true);
		viewport.scrollTo({
			top: viewport.scrollHeight,
			behavior: isGrowing.current ? "instant" : "smooth",
		});
	};

	return [containerRef, showScrollButton, scrollToBottom];
}