
let osichatSocket;
let isOpen = false;
let chatLoaded = false;
let newMessageCount = 0;
let atBottom = true;


function scrollBottom() {
    const conversationContainer = document.getElementById('conversation');

    if (conversationContainer) {
        conversationContainer.scrollTo({
            top: conversationContainer.scrollHeight,
            behavior: 'smooth'
        });
    }
}


function isScrolledToBottom(element) {
    return element && (element.scrollHeight - element.scrollTop <= element.clientHeight + 200); 
}



function setupScrollEventListener() {
    const conversationContainer = document.getElementById('conversation');

    if (conversationContainer) {
        conversationContainer.addEventListener('scroll', () => {
            if (isScrolledToBottom(conversationContainer)) {
                if (!atBottom) {
                    hideNewMessageNotification();
                    atBottom = true; // Update flag when user scrolls to the bottom
                }
            } else {
                atBottom = false; // Update flag if user is not at the bottom
            }
        });
    }
}

function showNewMessageNotification(count) {
    const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
    const newMessagesCounter = document.getElementById('newMessagesCounter');
    if (newMessagesPopMessage && newMessagesCounter) {
        newMessagesCounter.textContent = count;
        newMessagesPopMessage.classList.remove('hidden');
    }
}

function hideNewMessageNotification() {
    const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
    if (newMessagesPopMessage) {
        newMessagesPopMessage.classList.add('hidden');
        newMessageCount = 0;
        const newMessagesCounter = document.getElementById('newMessagesCounter');
        if (newMessagesCounter) {
            newMessagesCounter.textContent = newMessageCount;
        }
        scrollBottom()
    }
}


function newMessageNotification() {
    const notificationSound = document.getElementById('notification-sound');
    notificationSound.play();

    const conversationContainer = document.getElementById('conversation');

    if (!isScrolledToBottom(conversationContainer)) {
        let count = newMessageCount + 1;
        newMessageCount = count;
        showNewMessageNotification(count);
    } else {
        scrollBottom();
    }
    
}


// FUNCTION TO FETCH THE SESSION ID
async function fetchSessionID() {
    let session_id = 'Unknown';
    while (session_id === 'Unknown') {
        try {
            const response = await fetch(`${protocol}://${ositcomDomain}/get-client-session/`);
            const data = await response.json();
            if (data.session_id) {
                session_id = data.session_id;
            }
        } catch (error) {
            console.error('Error fetching session ID:', error);
        }
    }
    return session_id;
}

// FUNCTIONS TO SHOW & HIDE THE LOADER
function showLoader() {
    const osichatLoader = document.getElementById('osichatLoader');
    if (osichatLoader) {
        osichatLoader.classList.remove('hidden');
    }
}

function hideLoader() {
    const osichatLoader = document.getElementById('osichatLoader');
    if (osichatLoader) {
        osichatLoader.classList.add('hidden');
    }
}



// FUNCTION TO APPEND THE TEXTAREA SCRIPT
function appendTextAreaScript(domain, chatDiv) {
    const textareaScript = document.createElement('script');
    textareaScript.type = 'text/javascript';
    textareaScript.src = `${protocol}://${domain}/static/js/osichat/textarea.js`;
    chatDiv.appendChild(textareaScript);
}

// FUNCTION TO HANDLE FORM SUBMISSION
function handleFormSubmission(form, eventType, osichatSocket) {
    form.addEventListener('submit', function (event) {
        event.preventDefault();

        const formData = new FormData(form);
        const eventMessage = { 'event_type': eventType };

        formData.forEach((value, key) => {
            eventMessage[key] = value;
        });
        if (eventType === 'start_conversation') {
            showLoader(); 
        }
        osichatSocket.send(JSON.stringify(eventMessage));
        form.reset();
    });
}

// FUNCTION TO HANDLE LOAD CHAT EVENT
function handleLoadChatEvent(data, osichatSocket) {
    chatLoaded = true;
    hideLoader();
    let chatDiv = document.getElementById('roomContainer'); // CASE WHERE WIDGET IS ALREADY LOADED, DISPLAY THE CHAT PAGES(START/CONVERSATION) IN ROOM CONTAINER
    if (!chatDiv) {
        chatDiv = document.getElementById('osichat'); // CASE WHERE WIDGET IS NOT LOADED, DISPLAY THE WHOLE CHATWIDGET IN OSICHAT
    }

    chatDiv.innerHTML = data.html;
    scrollBottom();


    if (isOpen) { // If chat widget isOpen  mark all messages as read by guest else just return number of unread messages
        osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
    } else {
        osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
    }


    if (!document.querySelector(`script[src="${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js"]`)) {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = `${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js`;
        chatDiv.appendChild(script);
    }
    
    const startChatContainer = document.getElementById('startChat'); //Case where returned is start-conversation.html
    if (startChatContainer) {
        handleFormSubmission(startChatContainer, 'start_conversation', osichatSocket);
    }

    const sendMessageContainer = document.getElementById('sendMessage'); //Case where returned is chat-room.html
    if (sendMessageContainer) {
        appendTextAreaScript(osinaDomain, chatDiv);
        handleFormSubmission(sendMessageContainer, 'send_message', osichatSocket);

        const uploadScript = document.createElement('script');
        uploadScript.type = 'text/javascript';
        uploadScript.src = `${protocol}://${osinaDomain}/static/js/osichat/upload-file.js`;
        chatDiv.appendChild(uploadScript);

        const endChatScript = document.createElement('script');
        endChatScript.type = 'text/javascript';
        endChatScript.src = `${protocol}://${osinaDomain}/static/js/osichat/end-chat.js`;
        chatDiv.appendChild(endChatScript);

        const endChatButton = document.getElementById('endChat');
        endChatButton.classList.remove('hidden')
    }

    const sendReviewContainer = document.getElementById('reviewContainer');  //Case where returned is ended-chat.html
    if (sendReviewContainer) {
        const sendReviewScript = document.createElement('script');
        sendReviewScript.type = 'text/javascript';
        sendReviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
        chatDiv.appendChild(sendReviewScript);
    }
}


// FUNCTION TO INITIALIZE WEB SOCKET CONNECTION
async function initializeChatWebSocket() {
    const session_id = await fetchSessionID();
    let osichatSocketUrl = `${wsScheme}://${osinaDomain}/ws/osichat/${session_id}/`;
    osichatSocket = new WebSocket(osichatSocketUrl);

    osichatSocket.onopen = () => {
        if(!chatLoaded){
            osichatSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_guest', 'reconnecting': 'False'}));
        }else{
            osichatSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_guest', 'reconnecting': 'True'}));
        }
    };

    osichatSocket.onmessage = function (e) {
        const data = JSON.parse(e.data);
        const typingDiv = document.getElementById('typing');
        const messagesDiv = document.getElementById('messages');
        switch (data.event_type) {
            case 'load_chat':
                handleLoadChatEvent(data, osichatSocket);
                break;
            case 'start_conversation':
                handleLoadChatEvent(data, osichatSocket);
                break;
            case 'typing': 
                if(!typingDiv && data.user){
                    messagesDiv.insertAdjacentHTML('beforeend', data.html);
                }
                break;
            case 'stopped_typing':
                if (typingDiv) {
                    typingDiv.remove();
                }
                break;
            case 'send_message':
                if (isOpen) { // If chat widget isOpen (declared in chat-toggle.js) mark all messages as read by guest else just return number of unread messages
                    osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
                } else {
                    osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
                }
                messagesDiv.insertAdjacentHTML('beforeend', data.html);

                const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
                newMessagesPopMessage.addEventListener('click', hideNewMessageNotification);

                if (data.user) { // If it is sent by an Osina user play a notification sound for the guest
                    if (typingDiv) {
                        typingDiv.remove();
                    }
                    newMessageNotification();
                    setupScrollEventListener();
                }
                break;
            case 'uploaded_file':
                if (isOpen) { 
                    osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
                } else {
                    osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
                }
                const uploadingDiv = document.getElementById(`uploading-${data.file_name}`);
                if (uploadingDiv) {
                    uploadingDiv.outerHTML = data.html;
                    if (!data.user) {
                        scrollBottom();
                    } else {
                        newMessageNotification();
                    }
                }
                else{
                    document.getElementById('messages').insertAdjacentHTML('beforeend', data.html);
                    if (!data.user) {
                        scrollBottom();
                    } else {
                        newMessageNotification();
                    }
                }
                break;
            case 'update_read_messages':  
                const unreadMessages = document.getElementById(`unreadMessages`);
                if (!isOpen) {   
                    unreadMessages.classList.remove('hidden');
                    unreadMessages.innerHTML = data.html;
                    const script = document.createElement('script');
                    script.src = `${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js`; 
                    document.body.appendChild(script);
                } else {
                    unreadMessages.classList.add('hidden');
                }
                break;
            case 'ended_chat':
                const currentChat = document.getElementById(`roomContainer`);
                if (currentChat) {
                    currentChat.innerHTML = data.html;
                    scrollBottom();
                }
                document.getElementById(`endChatConfirmationContainer`).classList.add('hidden');
                document.getElementById(`endChat`).classList.add('hidden');
                const sendReviewScript = document.createElement('script');
                sendReviewScript.type = 'text/javascript';
                sendReviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
                currentChat.appendChild(sendReviewScript);
                break;
            case 'submit_review':
                const submitReview = document.getElementById(`reviewContainer`);
                if (submitReview) {
                    submitReview.innerHTML = data.html;
                }
                const reviewScript = document.createElement('script');
                reviewScript.type = 'text/javascript';
                reviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
                submitReview.appendChild(reviewScript);
                break;
            default:
                console.log('Unknown event type:', data.event_type);
        }
    };

    osichatSocket.onclose = () => {
        showLoader();
        setTimeout(() => {
            console.log('Attempting to reconnect to WebSocket...');
            initializeChatWebSocket();
        }, 2000);
    };

    osichatSocket.onerror = (error) => {
        console.log('WebSocket error:', error);
        showLoader();
    };
}


window.addEventListener('offline', () => {
    showLoader();
    if (osichatSocket) {
        osichatSocket.close();
    }
});

// INITIALIZE CHAT WEB SOCKET
initializeChatWebSocket();
