import {useCallback, useEffect, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import Message from "../message";
import {scrollMCToTheBottom} from "../../../../../../../../../../../../helpers";
import {getChatUserInfo} from "../../../../helpers";

export default function Body({chat, messages, hasMore, loadMore, isFetched, loading, setDetailsOpen, notifications}) {
    const mcRef = useRef(null);
    const scrolledRef = useRef(false);
    const [previousMessageCount, setPreviousMessageCount] = useState(0);
    const [isLoadingMore, setIsLoadingMore] = useState(false);
    const lastScrolledHeight = useRef(0);
    const lastScrollTop = useRef(0);

    useEffect(() => {
        if (isFetched) {
            scrollMCToTheBottom(mcRef.current, scrolledRef);
        }
    }, [isFetched]);

    // Preserve scroll position when loading more messages
    useEffect(() => {
        const container = mcRef.current;
        if (!container) {
            return;
        }

        const currentMessageCount = messages.length;

        // If we have more messages than before, we're loading more
        if (currentMessageCount > previousMessageCount && previousMessageCount > 0 && isLoadingMore) {
            // Adjust scroll position to maintain the same relative position
            container.scrollTop = container.scrollHeight - lastScrolledHeight.current;
            setIsLoadingMore(false);
        }

        setPreviousMessageCount(currentMessageCount);
    }, [messages.length, previousMessageCount, isLoadingMore]);

    // Handle scroll to load more messages
    const handleScroll = useCallback(() => {
        const container = mcRef.current;
        if (!container || !hasMore || loading > 0 || isLoadingMore) {
            return;
        }

        const {scrollTop, scrollHeight} = container;

        // Determine scroll direction
        const isScrollingUp = scrollTop < lastScrollTop.current;

        // Update last scroll position
        lastScrollTop.current = scrollTop;
        // Update last scrolled height
        lastScrolledHeight.current = scrollHeight - scrollTop;

        // Only trigger if scrolling up and near the top (within 50px)
        if (isScrollingUp && scrollTop < 50) {
            setIsLoadingMore(true);
            loadMore();
        }
    }, [hasMore, loading, loadMore, isLoadingMore]);

    // Add scroll event listener
    useEffect(() => {
        const container = mcRef.current;
        if (!container) return;

        container.addEventListener('scroll', handleScroll);
        return () => {
            container.removeEventListener('scroll', handleScroll);
        };
    }, [handleScroll]);

    const userInfo = getChatUserInfo(chat?.user);

    /**
     * Find agent info for a message at given index
     * For connection messages, look forward for the first agent
     * For disconnection messages, look backward for the last agent
     */
    const findAgentForMessage = (messageIndex, direction = 'forward') => {
        if (direction === 'forward') {
            // Look forward for agent joined
            for (let i = messageIndex + 1; i < messages.length; i++) {
                if (messages[i].agent) {
                    return messages[i].agent;
                }
            }
        } else {
            // Look backward for agent left
            for (let i = messageIndex - 1; i >= 0; i--) {
                if (messages[i].agent) {
                    return messages[i].agent;
                }
            }
        }
        return null;
    };

    return (
        <div className="lbaic-settings-chats-content-body">
            <div
                ref={mcRef}
                className="lbaic-settings-chats-content-body-in lbaic-settings-scroll-y lbaic-settings-scroll-style"
            >
                {hasMore && isLoadingMore && (
                    <div className="lbaic-settings-chats-loading-indicator">
                        <div className="lbaic-settings-chats-loading-spinner">
                            <span>{__('Loading', 'limb-chatbot')}...</span>
                        </div>
                    </div>
                )}
                {messages.map((message, index) => {
                    const isNewRole = !index || messages[index - 1].role !== message.role;

                    // Find agent info for connection/disconnection messages
                    const joinedAgent = findAgentForMessage(index, 'forward');
                    const leftAgent = findAgentForMessage(index, 'backward');

                    return (
                        <Message
                            key={message.uuid}
                            message={message}
                            messageIndex={index}
                            userInfo={userInfo}
                            isNewRole={isNewRole}
                            setDetailsOpen={setDetailsOpen}
                            notifications={notifications}
                            joinedAgent={joinedAgent}
                            leftAgent={leftAgent}
                        />
                    )
                })}
            </div>
        </div>
    );
}