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, joinRoom } from '../socket/socket.tsx';
import Cookies from 'js-cookie';
import { getMessages, setContactStatus } from '../api/contactsApi.tsx';
import axios from 'axios';
import ParticipantsBar from '@/components/chat/ParticipantsBar.tsx';

export type MeProps = {
  isGroupAdmin: boolean;
  isGroupOwner: boolean;
};

export type ChatMessagesProps = {
  sender: string;
  message: string;
  recipient: string; // conversation_id
  message_id: number;
  pending: boolean;
  attachment_urls: string[] | null;
  sender_id: string;
  conversation_id: string;
  sent_at: Date;
};

export type ContactsProps = {
  read: boolean;
  username: string;
  user_id: string;
  id: number;
  type: 'direct' | 'group';
  conversation_id: string;
  last_active: string;
};

function Chat() {
  const [contactsList, setContactsList] = useState<ContactsProps[]>([]);
  const [currentContact, setCurrentContact] = useState<ContactsProps | null>(
    null,
  );
  const [cursor, setCursor] = useState<number>(0);
  const [messages, setMessages] = useState<ChatMessagesProps[]>([]);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [hasMoreMessages, setHasMoreMessages] = useState<boolean>(true);
  const [me, setMe] = useState<MeProps>({
    isGroupAdmin: false,
    isGroupOwner: false,
  });

  useEffect(() => {
    const token = Cookies.get('token');
    if (token) {
      initializeSocket(token);
    }
    const storedContact = localStorage.getItem('contact');
    if (storedContact) {
      try {
        const parsedContact = JSON.parse(storedContact);
        if (parsedContact) {
          initializeContact(parsedContact);
        }
      } catch (error) {
        console.error('Failed to parse stored contact:', error);
        localStorage.removeItem('contact');
      }
    }
  }, []);

  async function initializeContact(newContact: ContactsProps) {
    setMessages([]); // Clear messages from previous contact
    localStorage.setItem('contact', JSON.stringify(newContact)); // Set current contact in localstorage
    setCurrentContact(newContact);
    console.log('Initialized contact: ', newContact);
    try {
      const joinResult = await joinRoom(newContact.conversation_id);
      if (!joinResult.success) {
        setErrorMessage(joinResult.message);
        return false;
      }
      try {
        await fetchMessages(newContact.conversation_id);
      } catch (e) {
        console.error('Failed to fetch messages: ', e);
        return false;
      }
      setContactsList((prevContacts) =>
        prevContacts.map((c) =>
          c.username === newContact.username ? { ...c, read: true } : c,
        ),
      );
      console.log('Current contact is now: ', newContact);
      return true;
    } catch (e) {
      console.error('Failed to initialize contact:', e);
      return false;
    }
  }

  const fetchMessages = async (conversation_id: string) => {
    console.log('Fetching messages for: ', conversation_id);
    try {
      const messages = await getMessages(conversation_id);
      if (messages.messages.length < 50) {
        setHasMoreMessages(false);
        setErrorMessage('No more messages found');
      }

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

      messages.messages.forEach(messageHandler);
    } catch (e) {
      if (axios.isAxiosError(e)) {
        setErrorMessage(e.message);
      }
    }
  };

  const fetchPreviousMessages = async (contact: string | null) => {
    if (!hasMoreMessages) {
      return;
    }

    console.log(
      'Fetching messages for: ',
      contact,
      'with cursor: ',
      cursor,
      'hasmoremessages: ',
      hasMoreMessages,
    );

    try {
      const messages = await getMessages(contact, cursor, 50);
      if (messages.messages.length < 50) {
        setHasMoreMessages(false);
        setErrorMessage('No more messages found');
      }
      messages.messages.forEach((msg) => {
        setMessages((prevMessages) => {
          if (!prevMessages.some((m) => m.message_id === msg.message_id)) {
            const messageWithDate = {
              ...msg,
              sent_at: new Date(msg.sent_at),
            };

            return [messageWithDate, ...prevMessages];
          }
          return prevMessages;
        });
      });

      setCursor(() => {
        return Math.min(
          ...messages.messages.map((message) => message.message_id),
        );
      });
    } catch (e) {
      if (axios.isAxiosError(e)) {
        setErrorMessage(e.message);
      }
    }
  };

  function messageHandler(msg: ChatMessagesProps) {
    setMessages((prevMessages) => {
      // Check if the message already exists in the state
      if (!prevMessages.some((m) => m.message_id === msg.message_id)) {
        // Convert sent_at to Date object before adding to state
        const messageWithDate = {
          ...msg,
          sent_at: new Date(msg.sent_at),
        };
        return [...prevMessages, messageWithDate];
      }
      return prevMessages;
    });
  }

  function updateContactStatus(contactObj: ContactsProps, read: boolean) {
    console.log('Update contact status: ', contactObj);

    setContactsList((prevContacts) =>
      prevContacts.map((contact) => {
        if (contact.conversation_id === contactObj.conversation_id) {
          if (!contactObj.read) {
            setContactStatus(contactObj.conversation_id, 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}
            setErrorMessage={setErrorMessage}
          />
          <hr />
          <UserProfile />
        </div>

        {/*Chat area */}
        <div className="text-white bg-[#121212] flex flex-col h-screen flex-grow">
          <div className="flex-shrink-0">
            <ContactProfile contact={currentContact} />
          </div>
          <hr />
          {/* Messages and Participants Container */}
          <div className="flex flex-grow overflow-hidden">
            {/* Messages Container */}
            <div className="flex-grow overflow-x-hidden overflow-y-auto">
              <MessagesArea
                messages={messages}
                setMessages={setMessages}
                currentContact={currentContact}
                updateContactStatus={updateContactStatus}
                messageHandler={messageHandler}
                setContactsList={setContactsList}
                fetchPreviousMessages={fetchPreviousMessages}
                errorMessage={errorMessage}
                contactsList={contactsList}
                me={me}
              />
            </div>

            {/* Participants Bar */}
            {currentContact?.type == 'group' ? (
              <div className="w-80 bg-[#1E1E1E] flex-shrink-0">
                <ParticipantsBar
                  setMe={setMe}
                  me={me}
                  initializeContact={initializeContact}
                  currentContact={currentContact}
                />
              </div>
            ) : null}
          </div>

          <div className="flex-shrink-0 mb-2 mt-0">
            {currentContact && currentContact.username?.length >= 4 ? (
              <MessageForm contact={currentContact} messages={messages} />
            ) : null}
          </div>
        </div>
      </div>
    </>
  );
}

export default Chat;
