import { useContext, useEffect, useRef, useState } from 'react';
import { socket } from '@/socket/socket.ts';
import { sendContact } from '@/api/contactsApi.tsx';
import LoadingWheel from '../LoadingWheel.tsx';
import AnimatedMessage from '@/components/chat/chatArea/AnimatedMessage.tsx';
import { ChatMessagesProps } from '@/types/types.ts';
import { useChat } from '@/context/chat/useChat.ts';
import { AuthContext } from '@/utils/AuthProvider.tsx';

function MessagesArea() {
  const {
    messages,
    setMessages,
    currentContact,
    updateContactStatus,
    messageHandler,
    setContactsList,
    errorMessage,
    fetchPreviousMessages,
  } = useChat();
  const containerRef = useRef<HTMLDivElement>(null);
  const { user } = useContext(AuthContext);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [shouldScrollToBottom, setShouldScrollToBottom] = useState(true);
  const previousMessagesLength = useRef(messages.length);

  const scrollToBottom = () => {
    const container = containerRef.current;
    if (container && shouldScrollToBottom) {
      container.scrollTop = container.scrollHeight;
    }
  };

  const handleScroll = async () => {
    const container = containerRef.current;
    if (!container) return;

    if (container.scrollTop === 0) {
      setIsLoading(true);
      setShouldScrollToBottom(false);
      const previousScrollHeight = container.scrollHeight;

      try {
        await fetchPreviousMessages(currentContact!.conversation_id);

        container.scrollTop = container.scrollHeight - previousScrollHeight;
      } catch (e) {
        console.error('Error fetching previous messages:', e);
      } finally {
        setIsLoading(false);
      }
    }

    const isAtBottom =
      container.scrollHeight - container.scrollTop <=
      container.clientHeight + 100;
    setShouldScrollToBottom(isAtBottom);
  };

  const deleteMessage = async (message_id: number) => {
    try {
      socket?.emit(
        'delete message',
        {
          message_id,
          conversation_id: currentContact?.conversation_id,
        },
        (response: { status: string; message: string }) => {
          if (response.status !== 'ok') {
            console.error('Failed to delete message: ', response.message);
          }
        },
      );
    } catch (e) {
      if (e instanceof Error) {
        console.error('Failed to delete message');
      }
    }
  };

  useEffect(() => {
    if (!socket) return;

    const currentContainer = containerRef.current;
    if (currentContainer) {
      currentContainer.addEventListener('scroll', handleScroll);
    }

    socket.on('chat message', (msg: ChatMessagesProps) => {
      console.log('Received message: ', msg);
      if (
        msg.conversation_id !== currentContact?.conversation_id &&
        msg.sender !== user?.username
      ) {
        setContactsList((prevContacts) => {
          // Find if contact already exists1
          const existingContact = prevContacts.find(
            (c) => c.conversation_id === msg.conversation_id,
          );

          if (!existingContact) {
            sendContact(msg.sender);
            return [
              ...prevContacts,
              {
                username: msg.sender,
                read: false,
                id: msg.message_id,
                user_id: msg.sender_id,
                conversation_id: msg.conversation_id,
                type: 'direct',
                last_active: new Date().toString(),
                last_message: msg.message,
                last_message_sender: msg.sender,
                last_message_time: new Date().toString(),
              },
            ];
          } else {
            return prevContacts.map((contact) =>
              contact.conversation_id === msg.conversation_id
                ? {
                    ...contact,
                    last_active: new Date().toString(),
                    last_message: msg.message,
                    last_message_sender: msg.sender,
                    last_message_time: new Date().toString(),
                  }
                : contact,
            );
          }
        });

        // Update contact status...
      } else {
        if (msg.conversation_id == currentContact?.conversation_id) {
          messageHandler(msg);

          setContactsList((prevContacts) => {
            const existingContact = prevContacts.find(
              (c) => c.conversation_id === msg.conversation_id,
            );

            if (!existingContact) {
              sendContact(msg.sender);
              return [
                ...prevContacts,
                {
                  username: msg.sender,
                  read: false,
                  id: msg.message_id,
                  user_id: msg.sender_id,
                  conversation_id: msg.conversation_id,
                  type: 'direct',
                  last_active: new Date().toString(),
                  last_message: msg.message,
                  last_message_sender: msg.sender,
                  last_message_time: new Date().toString(),
                },
              ];
            } else {
              return prevContacts.map((contact) =>
                contact.conversation_id === msg.conversation_id
                  ? {
                      ...contact,
                      last_active: new Date().toString(),
                      last_message: msg.message,
                      last_message_sender: msg.sender,
                      last_message_time: new Date().toString(),
                    }
                  : contact,
              );
            }
          });
        }
      }
    });

    socket.on(
      'delete message',
      (msg: { conversation_id: string; message_id: number }) => {
        console.log('deleted message from state');
        setMessages((prevMessages) =>
          prevMessages.filter(
            (message) => message.message_id !== msg.message_id,
          ),
        );
      },
    );

    return () => {
      if (!socket) {
        console.error('Socket not initialized');
        return;
      }

      if (currentContainer) {
        currentContainer.removeEventListener('scroll', handleScroll);
      }
      socket.off('chat message');
      socket.off('delete message');
    };
  }, [currentContact, user?.username, setContactsList, updateContactStatus]);

  useEffect(() => {
    const hasNewMessages = messages.length > previousMessagesLength.current;
    previousMessagesLength.current = messages.length;

    if (hasNewMessages && shouldScrollToBottom) {
      scrollToBottom();

      setTimeout(scrollToBottom, 100);
    }
  }, [messages, shouldScrollToBottom]);

  useEffect(() => {
    scrollToBottom();
  }, []);

  return (
    <div ref={containerRef} className="flex flex-col h-full overflow-y-auto">
      <p className="text-center text-gray-400">{errorMessage}</p>
      <ul className="flex-grow list-none">
        {isLoading ? <LoadingWheel /> : null}
        {messages.map((msg: ChatMessagesProps) => (
          <AnimatedMessage
            key={msg.message_id}
            message={msg}
            onDelete={deleteMessage}
          />
        ))}
      </ul>
    </div>
  );
}

export default MessagesArea;
