import MessageForm from '../components/chat/MessageForm.tsx';
import ContactProfile from '../components/chat/ContactProfile.tsx';
import UserProfile from '../components/chat/UserProfile.tsx';
import ContactForm from '../components/chat/ContactForm.tsx';
import MessagesArea from '../components/chat/MessagesArea.tsx';
import { useEffect, useState } from 'react';
import ContactsList from '../components/chat/ContactsList.tsx';
import { initializeSocket } from '../socket/socket.tsx';
import Cookies from 'js-cookie';
import { getMessages, setContactStatus } from '../api/contactsApi.tsx';

type ChatMessages = {
  sender: string;
  message: string;
  recipient: string;
  message_id: number;
  timestamp: string;
};
type ContactsProps = {
  usernamecontact: string;
  read: boolean;
};

type ContactObjProps = {
  usernamecontact: string;
  read: boolean;
};

function Chat() {
  const [contactsList, setContactsList] = useState<ContactsProps[]>([]);
  const [currentContact, setCurrentContact] = useState<string | null>(null);
  const [cursor, setCursor] = useState<number>(0);
  const [messages, setMessages] = useState<ChatMessages[]>([]);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  useEffect(() => {
    const token = Cookies.get('token');
    if (token) {
      initializeSocket(token);
    }
    const storedContact = localStorage.getItem('contact');
    if (storedContact) {
      InitializeContact(storedContact);
    }
  }, []);

  function InitializeContact(newContact: string) {
    setMessages([]); // Clear messages from previous contact
    localStorage.setItem('contact', newContact); // Set current contact in localstorage
    setCurrentContact(newContact); // Set state for current user (used in contactProfile.tsx and for filtering messages)
    console.log('Initialized contact');

    fetchMessages(newContact).catch((e) =>
      console.error('Failed to fetch messages: ', e),
    );
    setContactsList((prevContacts) =>
      prevContacts.map((c) =>
        c.usernamecontact === newContact ? { ...c, read: true } : c,
      ),
    );

    console.log('Current contact is now: ', newContact);
  }

  const fetchMessages = async (currentContact: string | null) => {
    console.log('Fetching messages for: ', currentContact);
    try {
      const messages = await getMessages(currentContact);

      setCursor(() => {
        return Math.min(
          ...messages.messages.map((message) => message.message_id),
        );
      });

      messages.messages.forEach(messageHandler);
    } catch (e) {
      setErrorMessage(e.response.data.message);
    }
  };

  const fetchPreviousMessages = async (contact: string | null) => {
    console.log('Fetching messages for: ', contact, 'with cursor: ', cursor);
    try {
      const messages = await getMessages(contact, cursor, 50);
      messages.messages.forEach((msg) => {
        setMessages((prevMessages) => {
          if (!prevMessages.some((m) => m.message_id === msg.message_id)) {
            return [msg, ...prevMessages];
          }
          return prevMessages;
        });
      });
      setCursor(() => {
        return Math.min(
          ...messages.messages.map((message) => message.message_id),
        );
      });
    } catch (e) {
      setErrorMessage(e.response.data.message);
    }
  };

  function messageHandler(msg: ChatMessages) {
    setMessages((prevMessages) => {
      // Check if the message already exists in the state
      if (!prevMessages.some((m) => m.message_id === msg.message_id)) {
        return [...prevMessages, msg];
      }
      return prevMessages;
    });
  }

  function updateContactStatus(contactObj: ContactObjProps, read: boolean) {
    setContactsList((prevContacts) =>
      prevContacts.map((contact) => {
        if (contact.usernamecontact === contactObj.usernamecontact) {
          if (!contactObj.read) {
            setContactStatus(contactObj.usernamecontact, read);
          }
          return { ...contact, read: read };
        } else {
          return contact;
        }
      }),
    );
  }

  return (
    <>
      <div className="text-white flex h-screen">
        {/*Sidebar*/}
        <div className="h-screen bg-[#1E1E1E] flex flex-col">
          <ContactForm
            setContactsList={setContactsList}
            InitializeContact={InitializeContact}
          />
          <ContactsList
            InitializeContact={InitializeContact}
            contactsList={contactsList}
            setContactsList={setContactsList}
            setCurrentContact={setCurrentContact}
            updateContactStatus={updateContactStatus}
            setMessages={setMessages}
            currentContact={currentContact}
          />
          <hr />
          <UserProfile />
        </div>
        {/*Chat area */}
        <div className="text-white bg-[#121212] flex flex-col h-screen w-full">
          <div className="flex-shrink-0">
            <ContactProfile contact={currentContact} />
          </div>
          <hr className="flex-shrink-0" />
          <div className="flex-grow overflow-x-hidden overflow-y-auto m-2">
            <MessagesArea
              messages={messages}
              setMessages={setMessages}
              currentContact={currentContact}
              setContactStatus={setContactStatus}
              updateContactStatus={updateContactStatus}
              messageHandler={messageHandler}
              setContactsList={setContactsList}
              fetchPreviousMessages={fetchPreviousMessages}
              errorMessage={errorMessage}
            />
          </div>
          <div className="flex-shrink-0 mb-2 mt-0">
            {currentContact && currentContact.length >= 4 ? (
              <MessageForm contact={currentContact} />
            ) : null}
          </div>
        </div>
      </div>
    </>
  );
}

export default Chat;
