import { jsx } from "react/jsx-runtime";
import react from "react";
import { AutopilotChatEvent, AutopilotChatInterceptableEvent, AutopilotChatInternalEvent, CHAT_SCROLL_BOTTOM_BUFFER, CHAT_WIDTH_FULL_SCREEN_MAX_WIDTH } from "../service/index.js";
import { useChatService } from "./chat-service.provider.js";
import { useStreaming } from "./streaming-provider.js";
const AutopilotChatScrollContext = /*#__PURE__*/ react.createContext(null);
const AutopilotChatScrollProvider = ({ children })=>{
    const chatService = useChatService();
    const { streaming } = useStreaming();
    const contentRef = react.useRef(null);
    const previousHeightRef = react.useRef(0);
    const isDraggingScrollBarRef = react.useRef(false);
    const useInstantScrollRef = react.useRef(true);
    const isLoadingMoreMessagesRef = react.useRef(false);
    const shouldShowLoadingMoreMessagesRef = react.useRef(true);
    const prependingRef = react.useRef(false);
    const scrollTopBeforePrependRef = react.useRef(0);
    const scrollHeightBeforePrependRef = react.useRef(0);
    const [overflowContainer, setOverflowContainer] = react.useState(null);
    const [autoScroll, setAutoScroll] = react.useState(true);
    const [isOverflow, setIsOverflow] = react.useState(false);
    const [isContainerWide, setIsContainerWide] = react.useState(false);
    const checkOverflow = react.useCallback(()=>{
        if (overflowContainer) {
            const hasOverflow = overflowContainer.scrollHeight > overflowContainer.clientHeight;
            setIsOverflow(hasOverflow);
        }
    }, [
        overflowContainer
    ]);
    const checkContainerWidth = react.useCallback(()=>{
        if (overflowContainer) {
            const containerWidth = overflowContainer.clientWidth;
            const isWide = containerWidth > parseInt(CHAT_WIDTH_FULL_SCREEN_MAX_WIDTH, 10);
            setIsContainerWide(isWide);
        }
    }, [
        overflowContainer
    ]);
    const scrollToBottom = react.useCallback(({ force = false, behavior = 'smooth' } = {})=>{
        if (!force && !autoScroll) return;
        if (!autoScroll && force) setAutoScroll(true);
        if (overflowContainer) overflowContainer.scrollTo({
            top: overflowContainer.scrollHeight,
            behavior: streaming ? 'instant' : behavior
        });
    }, [
        autoScroll,
        overflowContainer,
        streaming
    ]);
    const handleResize = react.useCallback(()=>{
        if (!contentRef.current || !overflowContainer) return;
        const newHeight = contentRef.current.scrollHeight;
        checkOverflow();
        if (prependingRef.current) {
            const heightDifference = newHeight - scrollHeightBeforePrependRef.current;
            const newScrollTop = scrollTopBeforePrependRef.current + heightDifference;
            overflowContainer.scrollTo({
                top: newScrollTop,
                behavior: 'instant'
            });
            prependingRef.current = false;
            previousHeightRef.current = newHeight;
            return;
        }
        if (!autoScroll) {
            previousHeightRef.current = newHeight;
            return;
        }
        if (newHeight > previousHeightRef.current) {
            const distance = overflowContainer.scrollHeight - overflowContainer.scrollTop - overflowContainer.clientHeight;
            const isNearBottom = distance < CHAT_SCROLL_BOTTOM_BUFFER;
            scrollToBottom({
                force: true,
                behavior: isNearBottom || streaming || useInstantScrollRef.current ? 'instant' : 'smooth'
            });
        }
        previousHeightRef.current = newHeight;
    }, [
        contentRef,
        autoScroll,
        scrollToBottom,
        streaming,
        overflowContainer,
        checkOverflow
    ]);
    const handleWheel = react.useCallback((event)=>{
        if (!overflowContainer) return;
        if (event.deltaY < 0 && overflowContainer.scrollHeight > overflowContainer.clientHeight) setAutoScroll(false);
        else if (event.deltaY > 0 && overflowContainer.scrollHeight - overflowContainer.scrollTop - overflowContainer.clientHeight < CHAT_SCROLL_BOTTOM_BUFFER) setAutoScroll(true);
    }, [
        setAutoScroll,
        overflowContainer
    ]);
    const handleScroll = react.useCallback(()=>{
        if (!overflowContainer) return;
        if (0 === overflowContainer.scrollTop && !isLoadingMoreMessagesRef.current && shouldShowLoadingMoreMessagesRef.current && chatService?.getConfig()?.paginatedMessages) {
            chatService._eventBus.publish(AutopilotChatEvent.ConversationLoadMore);
            chatService.__internalService__.publish(AutopilotChatInternalEvent.SetIsLoadingMoreMessages, true);
        }
    }, [
        overflowContainer,
        chatService,
        isLoadingMoreMessagesRef
    ]);
    const handleKeyDown = react.useCallback((event)=>{
        if (!overflowContainer) return;
        if ('ArrowUp' === event.key) setAutoScroll(false);
        if ('ArrowDown' === event.key) {
            const distance = overflowContainer.scrollHeight - overflowContainer.scrollTop - overflowContainer.clientHeight;
            if (distance < CHAT_SCROLL_BOTTOM_BUFFER) setAutoScroll(true);
        }
    }, [
        overflowContainer
    ]);
    const handleMouseDown = react.useCallback((event)=>{
        if (!overflowContainer) return;
        overflowContainer.focus();
        const scrollbarWidth = overflowContainer.offsetWidth - overflowContainer.clientWidth;
        const scrollbarXStart = overflowContainer.getBoundingClientRect().right - scrollbarWidth;
        if (event.clientX >= scrollbarXStart) {
            isDraggingScrollBarRef.current = true;
            setAutoScroll(false);
        }
    }, [
        overflowContainer
    ]);
    const handleMouseUp = react.useCallback(()=>{
        if (isDraggingScrollBarRef.current) {
            isDraggingScrollBarRef.current = false;
            if (overflowContainer) {
                const distance = overflowContainer.scrollHeight - overflowContainer.scrollTop - overflowContainer.clientHeight;
                if (distance < CHAT_SCROLL_BOTTOM_BUFFER) setAutoScroll(true);
            }
        }
    }, [
        overflowContainer
    ]);
    react.useEffect(()=>{
        const content = contentRef.current;
        if (!content || !overflowContainer || !chatService) return;
        checkOverflow();
        checkContainerWidth();
        const resizeObserver = new ResizeObserver(handleResize);
        resizeObserver.observe(content);
        const containerResizeObserver = new ResizeObserver(()=>{
            checkOverflow();
            checkContainerWidth();
        });
        containerResizeObserver.observe(overflowContainer);
        overflowContainer.addEventListener('mousedown', handleMouseDown);
        overflowContainer.addEventListener('mouseup', handleMouseUp);
        overflowContainer.addEventListener('keydown', handleKeyDown);
        overflowContainer.addEventListener('wheel', handleWheel, {
            passive: true
        });
        overflowContainer.addEventListener('scroll', handleScroll, {
            passive: true
        });
        const unsubscribeRequestIntercept = chatService.intercept(AutopilotChatInterceptableEvent.Request, ()=>{
            setAutoScroll(true);
            useInstantScrollRef.current = false;
        });
        const unsubscribeNewChat = chatService.on(AutopilotChatEvent.NewChat, ()=>{
            setAutoScroll(true);
            useInstantScrollRef.current = false;
        });
        const unsubscribeOpenConversation = chatService.on(AutopilotChatEvent.OpenConversation, ()=>{
            setAutoScroll(true);
        });
        const unsubscribeSetConversation = chatService.on(AutopilotChatEvent.SetConversation, ()=>{
            useInstantScrollRef.current = true;
        });
        const unsubscribeModeChange = chatService.on(AutopilotChatEvent.ModeChange, ()=>{
            useInstantScrollRef.current = true;
        });
        const unsubscribeToggleAutoScroll = chatService.__internalService__.on(AutopilotChatInternalEvent.ToggleAutoScroll, (autoScrollValue)=>{
            setAutoScroll(autoScrollValue);
        });
        const unsubscribeSetIsLoadingMoreMessages = chatService.__internalService__.on(AutopilotChatInternalEvent.SetIsLoadingMoreMessages, (value)=>{
            isLoadingMoreMessagesRef.current = value;
        });
        const unsubscribeShouldShowLoadingMoreMessages = chatService.__internalService__.on(AutopilotChatInternalEvent.ShouldShowLoadingMoreMessages, (value)=>{
            shouldShowLoadingMoreMessagesRef.current = value;
        });
        const unsubscribePrependOlderMessages = chatService.__internalService__.on(AutopilotChatInternalEvent.PrependOlderMessages, ()=>{
            if (overflowContainer && contentRef.current) {
                prependingRef.current = true;
                scrollTopBeforePrependRef.current = overflowContainer.scrollTop;
                scrollHeightBeforePrependRef.current = contentRef.current.scrollHeight;
            }
        });
        return ()=>{
            resizeObserver.disconnect();
            containerResizeObserver.disconnect();
            overflowContainer.removeEventListener('wheel', handleWheel);
            overflowContainer.removeEventListener('mousedown', handleMouseDown);
            overflowContainer.removeEventListener('mouseup', handleMouseUp);
            overflowContainer.removeEventListener('keydown', handleKeyDown);
            overflowContainer.removeEventListener('scroll', handleScroll);
            unsubscribeRequestIntercept();
            unsubscribeNewChat();
            unsubscribeOpenConversation();
            unsubscribeSetConversation();
            unsubscribeModeChange();
            unsubscribeToggleAutoScroll();
            unsubscribeSetIsLoadingMoreMessages();
            unsubscribeShouldShowLoadingMoreMessages();
            unsubscribePrependOlderMessages();
        };
    }, [
        handleResize,
        handleWheel,
        handleKeyDown,
        handleMouseUp,
        handleMouseDown,
        handleScroll,
        chatService,
        overflowContainer,
        checkOverflow,
        checkContainerWidth
    ]);
    const value = react.useMemo(()=>({
            autoScroll,
            scrollToBottom,
            overflowContainer,
            setOverflowContainer,
            contentRef,
            isOverflow,
            isContainerWide
        }), [
        autoScroll,
        scrollToBottom,
        overflowContainer,
        setOverflowContainer,
        contentRef,
        isOverflow,
        isContainerWide
    ]);
    return /*#__PURE__*/ jsx(AutopilotChatScrollContext.Provider, {
        value: value,
        children: children
    });
};
const useChatScroll = ()=>{
    const context = react.useContext(AutopilotChatScrollContext);
    if (!context) throw new Error('useChatScroll must be used within a AutopilotChatScrollProvider');
    return context;
};
export { AutopilotChatScrollProvider, useChatScroll };
