/**
 * @fileoverview Manages global chat state and polling functionality.
 * This file implements a singleton ChatManager that handles:
 * - Message polling and state management
 * - New message processing and event triggering
 * - Connection state tracking
 * - Resource cleanup
 */

// Global state and polling management
if (typeof window.ChatManager === 'undefined') {
    window.ChatManager = (function() {
        let instance = null;
        let pollInterval = null;
        
        /**
         * @typedef {Object} ConnectionState
         * @property {boolean} hasJoined - Whether the user has joined the conversation
         * @property {boolean} isConnected - Current connection status
         * @property {number|null} lastMessageId - ID of the last received message
         * @property {number} pollAttempts - Number of failed polling attempts
         */

        /**
         * @typedef {Object} ChatState
         * @property {Set<number>} addedMessageIds - Set of message IDs that have been processed
         * @property {Set<Object>} messageQueue - Queue of messages waiting to be processed
         * @property {ConnectionState} connectionState - Current connection state
         */

        const state = {
            addedMessageIds: new Set(),
            messageQueue: new Set(),
            connectionState: {
                hasJoined: false,
                isConnected: true,
                lastMessageId: null,
                pollAttempts: 0
            }
        };

        /**
         * Initializes a new ChatManager instance for a conversation.
         * Sets up message tracking and starts polling for new messages.
         * @function
         * @param {string} conversationId - The ID of the conversation to manage
         * @returns {Object} The ChatManager instance
         */
        function init(conversationId) {
            if (instance) {
                console.log('[ChatManager] Instance already exists, returning existing instance');
                return instance;
            }

            console.log('[ChatManager] Initializing new instance for conversation:', conversationId);

            // Initialize message IDs from existing messages
            $('.message').each(function() {
                const messageId = $(this).data('message-id');
                if (messageId) {
                    state.addedMessageIds.add(messageId);
                    state.connectionState.lastMessageId = Math.max(state.connectionState.lastMessageId || 0, messageId);
                    console.log('[ChatManager] Initialized with existing message:', {
                        messageId: messageId,
                        lastMessageId: state.connectionState.lastMessageId
                    });
                }
            });

            // Start polling for new messages
            startPolling(conversationId);

            instance = {
                state: state,
                cleanup: cleanup
            };

            return instance;
        }

        /**
         * Starts polling for new messages in the conversation.
         * Polls every 3 seconds and performs an initial fetch.
         * @function
         * @param {string} conversationId - The ID of the conversation to poll
         */
        function startPolling(conversationId) {
            console.log('[ChatManager] Starting polling for conversation:', conversationId);
            
            // Clear any existing polling
            if (pollInterval) {
                console.log('[ChatManager] Clearing existing polling interval');
                clearInterval(pollInterval);
            }

            // Poll every 3 seconds
            pollInterval = setInterval(() => {
                console.log('[ChatManager] Polling interval triggered');
                fetchNewMessages(conversationId);
            }, 3000);

            // Initial fetch
            console.log('[ChatManager] Performing initial message fetch');
            fetchNewMessages(conversationId);
        }

        /**
         * Fetches new messages from the server.
         * Uses the last message ID to only fetch new messages.
         * @function
         * @param {string} conversationId - The ID of the conversation to fetch messages from
         */
        function fetchNewMessages(conversationId) {
            const url = `/conversations/${conversationId}/messages`;
            const params = new URLSearchParams();
            
            if (state.connectionState.lastMessageId) {
                params.append('last_message_id', state.connectionState.lastMessageId);
            }

            console.log('[ChatManager] Fetching new messages:', {
                url: url,
                params: params.toString(),
                lastMessageId: state.connectionState.lastMessageId
            });

            fetch(`${url}?${params.toString()}`)
                .then(response => response.json())
                .then(data => {
                    console.log('[ChatManager] Received messages response:', {
                        success: data.success,
                        messageCount: data.messages ? data.messages.length : 0,
                        messages: data.messages
                    });

                    if (data.success && data.messages) {
                        state.connectionState.pollAttempts = 0;
                        processNewMessages(data.messages);
                    }
                })
                .catch(error => {
                    console.error('[ChatManager] Error fetching messages:', error);
                    state.connectionState.pollAttempts++;
                    
                    // If we've had too many failed attempts, try to reconnect
                    if (state.connectionState.pollAttempts > 5) {
                        console.log('[ChatManager] Too many failed attempts, restarting polling');
                        startPolling(conversationId);
                    }
                });
        }

        /**
         * Processes new messages and triggers events for each new message.
         * Updates the last message ID and tracks processed messages.
         * @function
         * @param {Array<Object>} messages - Array of new message objects to process
         */
        function processNewMessages(messages) {
            console.log('[ChatManager] Processing new messages:', {
                messageCount: messages.length,
                currentLastMessageId: state.connectionState.lastMessageId,
                existingMessageIds: Array.from(state.addedMessageIds)
            });

            messages.forEach(message => {
                console.log('[ChatManager] Processing message:', {
                    messageId: message.id,
                    alreadyAdded: state.addedMessageIds.has(message.id),
                    currentLastMessageId: state.connectionState.lastMessageId
                });

                if (!state.addedMessageIds.has(message.id)) {
                    state.addedMessageIds.add(message.id);
                    state.connectionState.lastMessageId = Math.max(state.connectionState.lastMessageId || 0, message.id);
                    console.log('[ChatManager] Triggering new_message event for message:', message.id);
                    // Trigger the new message event
                    $(document).trigger('new_message', [message]);
                } else {
                    console.log('[ChatManager] Skipping already added message:', message.id);
                }
            });
        }

        /**
         * Cleans up polling resources and resets the instance.
         * Should be called when the chat is no longer needed.
         * @function
         */
        function cleanup() {
            console.log('[ChatManager] Cleaning up polling');
            if (pollInterval) {
                clearInterval(pollInterval);
                pollInterval = null;
            }
            instance = null;
        }

        return {
            /**
             * Gets or creates a ChatManager instance for a conversation.
             * @function
             * @param {string} conversationId - The ID of the conversation to manage
             * @returns {Object} The ChatManager instance
             */
            getInstance: function(conversationId) {
                if (!instance) {
                    instance = init(conversationId);
                }
                return instance;
            }
        };
    })();
} 