import { addMinutes, format, sub } from 'date-fns';
import { useRef, useMemo, useState, useCallback, useEffect } from 'react';

import Stack from '@mui/material/Stack';
import InputBase from '@mui/material/InputBase';
import IconButton from '@mui/material/IconButton';

import { paths } from '@/routes/paths';
import { useRouter } from '@/hooks';

import { useMockedUser } from '@/hooks/use-mocked-user';

import { useGetContacts } from '@/shared/api/chat';

import Iconify from '@/shared/components/iconify';

import { IChatConversation, IChatConversationClient, IChatConversations, IChatMessage, IChatParticipant, IClient, MessageType } from '@/shared/types/chat';
import { useGetContactsTest, useGetConversation } from '@/shared/api/chat javalin';
import useWebSocket from 'react-use-websocket';
// import { getClientAuthorization } from '@/utils/authorization';
import useSWR, { mutate } from 'swr';
import EmojiPicker from '@/shared/components/emoji/EmojiPicker';
import { EmojiClickData } from 'emoji-picker-react';
import { createConversation, getOrCreateConversation, mutateConversation, mutateConversationInreact, mutateConversationInUpdate, mutateConversations, sendMessagee } from '@/shared/api/chatv2';
import uuidv4 from '@/utils/uuidv4';
import axios from 'axios';
import { forEach } from 'lodash';
import { fetcher } from '@/utils/axios';

// ----------------------------------------------------------------------

type Props = {
  recipients: IClient[];
  onAddRecipients: (recipients: IClient[]) => void;
  //
  disabled: boolean;
  selectedConversationId: string;
  onNewMessage: (message: IChatMessage) => void;
  replyTo: IChatMessage | null;
  onClearReply: () =>void;
};

export default function ChatMessageInput({
  recipients,
  onAddRecipients,
  //
  disabled,
  selectedConversationId,
  onNewMessage,
  replyTo,
  onClearReply,
}: Props) {
  const router = useRouter();
  // const clientAuthorization = getClientAuthorization();

  const {conversation} = useGetConversation(selectedConversationId);
  const isChannel = conversation?.typeConv === 'CHANNEL';


  const { user1 } = useMockedUser();

  const fileRef = useRef<HTMLInputElement>(null);

  const [message, setMessage] = useState('');

  const [messages, setMessages] = useState<IChatMessage[]>( []); // État pour stocker les messages de la conversation

  const [showPicker, setShowPicker] = useState(false);

  const [messageUp, setMessageUp] = useState('');
  

  const conv = conversation ? conversation : null;

  const destUuid = useMemo(() => {
    if (conv && conv.participants && conv.participants.length > 1) {
      return conv.participants.filter(participant => participant.uuid !== user1.uuid)[0].uuid;     
    }
    return null;
  }, [conv]);


  const { sendMessage ,lastMessage,readyState} = useWebSocket("ws://localhost:4000/chat", {
    queryParams: {

      "id": `${user1.uuid}`,
    },
    onOpen: () => {
      
      console.log('WebSocket connection established.');
      console.log("user uuid "+ user1.uuid);

    },
    onMessage: (event) => {
      const receivedMessage = JSON.parse(event.data);
      console.log('Received message:', receivedMessage);


      if (receivedMessage?.action === "deleted") {
        
        
        const deletedMessage = receivedMessage.message;
        // Mettez à jour l'état des messages pour supprimer le message approprié
        // setMessages(
        //   conversation.messages.filter((msg) => {          
        //     msg.uuid !== deletedMessage.uuid})
        // );
        onDeleteMessage(deletedMessage.uuid);
      }

      if (receivedMessage?.action === "updated") {
        
        
        const updatedMessage = receivedMessage.message;

        // Mettez à jour l'état des messages pour modifier le message approprié

        mutateConversationInUpdate(selectedConversationId,updatedMessage);
        
      }
      
      if (receivedMessage?.action === "reacted") {
        
        
        const reactedMessage = receivedMessage.message;

      

        // Mettez à jour l'état des messages pour modifier le message approprié

        mutateConversationInreact(selectedConversationId,reactedMessage);
  
        
      }

      if (receivedMessage.sender !== "Server") {
        const newMessage = {
          id: receivedMessage.userMessage.id,
          sourceUuid: receivedMessage.userMessage.sourceUuid,
          destinationUuid: receivedMessage.userMessage.destinationUuid,
          type: receivedMessage.userMessage.type,
          body: receivedMessage.userMessage.body,
          uuid: receivedMessage.userMessage.uuid,
          replyTo: receivedMessage.userMessage.replyTo ? {
            id: receivedMessage.userMessage.replyTo.id,
            uuid: receivedMessage.userMessage.replyTo.uuid,
            body: receivedMessage.userMessage.replyTo.body, // Ensure body is included
          } : null,
          // createdAt: new Date(),
          // owner: myContact,
          // update: receivedMessage.userMessage.update,
          reactions: [],
          date: sub(new Date(), { minutes: 1 }),
          // pined: false,
          conversation: receivedMessage.userMessage.conversation,
        };
        // Mettre à jour localement la conversation avec le nouveau message
        if(selectedConversationId !== ''){
          mutateConversation(receivedMessage.userMessage.conversation,newMessage);
        }
        
        mutateConversations(user1.id, receivedMessage.userMessage.conversation, newMessage) ;
        
        // setMessages((prevMessages) => [...prevMessages, newMessage]
        // );
        // onNewMessage(newMessage);
        
      }
    },
    onClose: (event) => {
      console.log("session closed", event)
    },
    onError: (event) => {
      console.log("session error", event)
    }
  });

  const myContact : IClient = {
      id: user1?.id,
      uuid: `${user1?.uuid}`,
      usernameType : 'EMAIL',
      username : `${user1?.username}`,
      firstname: `${user1?.firstname}`,
      lastname: `${user1?.lastname}`,
      avatarUrl:`${user1?.avatarUrl}`,
      phoneNumber:'', 
      status : 'online' as 'online' | 'offline',
      lastActivity: new Date()
    }

  const [newMessage, setNewMessage] = useState({
    sender: "",
    message: ""
});
  
const onDeleteMessage = (deletedMessageUuid:string) => {
   // Ajouter le message localement en utilisant mutate
  //  mutate(
  //   `http://localhost:4000/conversation/${selectedConversationId}`,
  //   (conversation: any) => {
  //     return {
  //       ...conversation,
  //       messages: [...(conversation?.messages || []),],
  //     };
  //   },
  //   false // Ne pas revalider les données après la mise à jour
  // );
  mutate(
          `http://localhost:4000/conversation/${selectedConversationId}`,
          (conversation: any) => {
            if (conversation && conversation.messages) {
            return {
                ...conversation,
                messages: conversation.messages.filter(
                    (msg : any) => msg.uuid !==deletedMessageUuid
                ),
            };
        }
        return conversation;
    }, false);
}

  
  const onSendMessage = () => {
    //
    const formatDate = (date: Date) => {
      return format(date, "yyyy-MM-dd'T'HH:mm:ss.SSS");
    };
    
    const currentDate = new Date();
    const newDate = formatDate(addMinutes(currentDate, 1));
    const formattedReplyTo = replyTo ? { ...replyTo, date: formatDate(new Date(replyTo.date)) } : null;

    const messageObject = {
        sourceUuid: myContact.uuid,
        destinationUuid: isChannel ? "" : (destUuid != null ? destUuid : recipients[0].uuid),
        type: "TEXT",
        body: message,
        date: newDate,
        uuid:uuidv4(),
        conversation: selectedConversationId,
        replyTo: formattedReplyTo,
    }

  
    // Ajouter le message localement en utilisant mutate
    

  mutateConversation(selectedConversationId,messageObject);
  mutateConversations(user1.id, selectedConversationId, messageObject) ;

  
    sendMessage(JSON.stringify(messageObject));
    onClearReply(); // Clear reply state after sending
    setNewMessage({
      ...newMessage,
      message: ""
  })


  
}



  const handleEmojiClick = (emojiData: EmojiClickData) => {
    // setMessageUp((prev) => prev + emojiData.emoji);
    setMessage((prev) => prev + emojiData.emoji);
    setShowPicker(false);
  };

  const handleAttach = useCallback(() => {
    if (fileRef.current) {
      fileRef.current.click();
    }
  }, []);

  const handleChangeMessage = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    setMessage(event.target.value);
  }, []);


  
  
  const sendNewMessage = async (recipient: IClient, messageText: string, index: number) => {
    const formatDate = (date: Date) => {
      return format(date, "yyyy-MM-dd'T'HH:mm:ss.SSS");
    };

    const currentDate = new Date();
    const newDate = formatDate(addMinutes(currentDate, 1));
    const formattedReplyTo = replyTo ? { ...replyTo, date: formatDate(new Date(replyTo.date)) } : null;

    const messageObject = {
        sourceUuid: myContact.uuid,
        destinationUuid: recipient.uuid,
        type: "TEXT",
        body: messageText,
        date: newDate,
        uuid: uuidv4(),
        conversation: "", // This will be set after the conversation is created or retrieved
        //replyTo: formattedReplyTo,
    };

    try {
        // Get or create the conversation
        const conversationId = await getOrCreateConversation(user1.uuid, recipient.uuid, user1.id);

        // Set the conversation ID in the message object
        messageObject.conversation = conversationId;

      
        // Send the message via WebSocket

        // Update the conversation state locally
      /*   mutateConversation(conversationId, messageObject);
        mutateConversations(user1.id, conversationId, messageObject);
        const cacheKey = `http://localhost:4000/conversations/${user1.id}`; */

        mutateConversation(conversationId, messageObject);
        mutateConversations(user1.id, conversationId, messageObject);
        sendMessage(JSON.stringify(messageObject));
      /*   if (index === recipients.length - 1) {
         
          //selectedConversationId = conversationId;
         
          // Optionally, navigate to the conversation of the first or last recipient
        /// router.push(`${paths.dashboard.chat}?id=${conversationId}`);
          
        } */
       
        if (index === recipients.length - 1) {
          // Update the conversation data
          const fullConversation = await fetcher(`http://localhost:4000/conversation/${conversationId}`);
          mutate(`http://localhost:4000/conversation/${conversationId}`, fullConversation, false);

          router.push(`${paths.dashboard.chat}?id=${conversationId}`);
        
        }

    } catch (error) {
        console.error("Error sending message:", error);
    }
};


  const handleSendMessage = useCallback(
    async (event: React.KeyboardEvent<HTMLInputElement>) => {
      try {
        if (event.key === 'Enter') {
          if (message) {
            if (selectedConversationId) {
              onSendMessage();
            } else {
              recipients.forEach((recipient, index) => {
                // Your code here
                 sendNewMessage(recipient, message, index);
            });
              
    
              onAddRecipients([]);
            }
          }
          setMessage('');
        }
      } catch (error) {
        console.error(error);
      }
    },
    [message, selectedConversationId, myContact.uuid, destUuid, recipients, user1.uuid, router, onSendMessage, onAddRecipients]
  );
  
  return (
    <>
      <Stack spacing={2} sx={{ p: 2 }}>
      
          <Stack >
            {showPicker && (
                <EmojiPicker onEmojiClick={handleEmojiClick} />
              )}
              
          </Stack>
      </Stack>
      
      <InputBase
        value={message}
        onKeyUp={handleSendMessage}
        onChange={handleChangeMessage}
        placeholder="Type a message"
        disabled={disabled}
        startAdornment={
          <IconButton onClick={()=>setShowPicker(!showPicker)}>
            <Iconify icon="eva:smiling-face-fill" />
          </IconButton>
        }
        endAdornment={
          <Stack direction="row" sx={{ flexShrink: 0 }}>
            <IconButton onClick={handleAttach}>
              <Iconify icon="solar:gallery-add-bold" />
            </IconButton>
            <IconButton onClick={handleAttach}>
              <Iconify icon="eva:attach-2-fill" />
            </IconButton>
            <IconButton>
              <Iconify icon="solar:microphone-bold" />
            </IconButton>
          </Stack>
        }
        sx={{
          px: 1,
          height: 56,
          flexShrink: 0,
          borderTop: (theme) => `solid 1px ${theme.palette.divider}`,
          fontFamily: 'Noto Color Emoji',
        }}
      />
      
      <input type="file" ref={fileRef} style={{ display: 'none' }} />
    </>
  );
}
