import { useApolloClient, useQuery } from "@apollo/client";
import axios from "axios";
import React, { useCallback, useContext, useEffect, useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import SocketContext from "../../contexts/SocketIO/socketContext";
import { GET_CONVERSATION_DETAILS } from "../../graphql/conversations.queries";
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import ChatConversationComponent from "./chat-conversation.component";

const mapStateToProps = createStructuredSelector({
  selectedConversation: selectSelectedConversation,
  bodyshop: selectBodyshop
});

export function ChatConversationContainer({ bodyshop, selectedConversation }) {
  const client = useApolloClient();
  const { socket } = useContext(SocketContext);
  const [markingAsReadInProgress, setMarkingAsReadInProgress] = useState(false);

  const {
    loading: convoLoading,
    error: convoError,
    data: convoData
  } = useQuery(GET_CONVERSATION_DETAILS, {
    variables: { conversationId: selectedConversation },
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only"
  });

  const updateCacheWithReadMessages = useCallback(
    (conversationId, messageIds) => {
      if (!conversationId || !messageIds || messageIds.length === 0) return;

      // Mark individual messages as read
      messageIds.forEach((messageId) => {
        client.cache.modify({
          id: client.cache.identify({ __typename: "messages", id: messageId }),
          fields: {
            read() {
              return true; // Mark message as read
            }
          }
        });
      });

      // Update aggregate unread count for the conversation
      client.cache.modify({
        id: client.cache.identify({ __typename: "conversations", id: conversationId }),
        fields: {
          messages_aggregate(existingAggregate) {
            return {
              ...existingAggregate,
              aggregate: {
                ...existingAggregate.aggregate,
                count: 0 // No unread messages remaining
              }
            };
          }
        }
      });
    },
    [client.cache]
  );

  // Handle WebSocket events
  useEffect(() => {
    if (!socket || !socket.connected) return;

    const handleConversationChange = (data) => {
      if (data.type === "conversation-marked-read") {
        const { conversationId, messageIds } = data;
        console.log("Conversation change received:", data);
        updateCacheWithReadMessages(conversationId, messageIds);
      }
    };

    socket.on("conversation-changed", handleConversationChange);

    return () => {
      socket.off("conversation-changed", handleConversationChange);
    };
  }, [socket, client, updateCacheWithReadMessages]);

  // Handle joining/leaving conversation
  useEffect(() => {
    if (!socket || !socket.connected) return;

    socket.emit("join-bodyshop-conversation", {
      bodyshopId: bodyshop.id,
      conversationId: selectedConversation
    });

    return () => {
      socket.emit("leave-bodyshop-conversation", {
        bodyshopId: bodyshop.id,
        conversationId: selectedConversation
      });
    };
  }, [selectedConversation, bodyshop, socket]);

  // Handle marking conversation as read
  const handleMarkConversationAsRead = async () => {
    if (!convoData || !selectedConversation || markingAsReadInProgress) return;

    const conversation = convoData.conversations_by_pk;
    if (!conversation) {
      console.warn(`No data found for conversation ID: ${selectedConversation}`);
      return;
    }

    const unreadMessageIds = conversation.messages
      ?.filter((message) => !message.read && !message.isoutbound)
      .map((message) => message.id);

    if (unreadMessageIds?.length > 0) {
      setMarkingAsReadInProgress(true);

      try {
        const payload = {
          conversation,
          imexshopid: bodyshop?.imexshopid,
          bodyshopid: bodyshop?.id
        };

        console.log("Marking conversation as read:", payload);

        await axios.post("/sms/markConversationRead", payload);

        // Update local cache
        updateCacheWithReadMessages(selectedConversation, unreadMessageIds);
      } catch (error) {
        console.error("Error marking conversation as read:", error.response?.data || error.message);
      } finally {
        setMarkingAsReadInProgress(false);
      }
    }
  };

  return (
    <ChatConversationComponent
      subState={[convoLoading, convoError]}
      conversation={convoData ? convoData.conversations_by_pk : {}}
      messages={convoData ? convoData.conversations_by_pk.messages : []}
      handleMarkConversationAsRead={handleMarkConversationAsRead}
    />
  );
}

export default connect(mapStateToProps, null)(ChatConversationContainer);
