import { useEffect } from 'react';

import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import {
  type AcknowledgementCommentCreatedSocket,
  type AcknowledgementCommentDeletedSocket,
  type AcknowledgementCommentReactionSocket,
  type AcknowledgementCommentUpdatedSocket,
} from 'src/pages/dashboard/acknowledgements/types';
import { addReaction, removeReaction } from 'src/utils/reactions';

import {
  decreaseAcknowledgementCommentAmount,
  dropChildCommentDataChildCommentList,
  dropChildCommentDataCommentList,
  dropChildLastCommentDataAcknowledgementList,
  dropCommentDataChildCommentList,
  dropCommentDataCommentList,
  dropLastCommentDataAcknowledgementList,
  increaseAcknowledgementCommentAmount,
  isChildCommentInData,
  isCommentInData,
  pushChildCommentDataChildCommentList,
  pushChildCommentDataCommentList,
  pushChildLastCommentDataAcknowledgementList,
  pushLastCommentData,
  setChildCommentDataChildCommentList,
  setChildCommentDataCommentList,
  setChildLastCommentDataAcknowledgementList,
  updateCommentListData,
  updateLastCommentData,
  updateReactionChildComment,
  updateReactionComment,
} from '../queries';

type UseAcknowledgementCommentsSocketProps = {
  id: number;
  openViewComments: boolean;
  openSendComment: boolean;
  commentAddCounter: number;
  setCommentAddCounter: (commentAddCounter: number) => void;
};

const {
  ACKNOWLEDGEMENT_COMMENT_CREATED,
  ACKNOWLEDGEMENT_COMMENT_UPDATED,
  ACKNOWLEDGEMENT_COMMENT_DELETED,
  NEW_POST_COMMENT_REACTION,
  REMOVE_POST_COMMENT_REACTION,
} = EVENTS_SOCKETS;

const useAcknowledgementCommentsSocket = ({
  id,
  openViewComments,
  openSendComment,
  commentAddCounter,
  setCommentAddCounter,
}: UseAcknowledgementCommentsSocketProps) => {
  const socket = useSocket();
  const { user } = useAuth();

  useEffect(() => {
    // Handler functions for socket events
    const eventHandlers = {
      // Create new comment
      createCommentPost: (createData: AcknowledgementCommentCreatedSocket) => {
        const { id: commentId, acknowledgmentId, parentId } = createData;
        const isCurrentPost = acknowledgmentId === id;

        if (isCurrentPost) {
          if (
            parentId &&
            !isChildCommentInData(acknowledgmentId, parentId, commentId)
          ) {
            pushChildCommentDataCommentList(
              acknowledgmentId,
              parentId,
              createData,
            );
            pushChildCommentDataChildCommentList(parentId, createData);
            pushChildLastCommentDataAcknowledgementList(
              acknowledgmentId,
              parentId,
              createData,
            );
          } else if (
            !parentId &&
            !isCommentInData(acknowledgmentId, commentId)
          ) {
            pushLastCommentData(id, createData);
            increaseAcknowledgementCommentAmount(id);
            setCommentAddCounter(commentAddCounter + 1);
          }
        }
      },

      // Update existing comment
      updateCommentPost: (updateData: AcknowledgementCommentUpdatedSocket) => {
        const { id: commentId, acknowledgmentId, parentId } = updateData;
        const isCurrentPost = acknowledgmentId === id;

        if (isCurrentPost) {
          if (parentId) {
            setChildCommentDataCommentList(
              acknowledgmentId,
              parentId,
              commentId,
              updateData,
            );
            setChildCommentDataChildCommentList(
              parentId,
              commentId,
              updateData,
            );
            setChildLastCommentDataAcknowledgementList(
              acknowledgmentId,
              parentId,
              commentId,
              updateData,
            );
          } else {
            updateCommentListData(acknowledgmentId, commentId, updateData);
            updateLastCommentData(acknowledgmentId, commentId, updateData);
          }
        }
      },

      // Delete comment
      deleteCommentPost: (deleteData: AcknowledgementCommentDeletedSocket) => {
        const { acknowledgmentId, commentId, parentId } = deleteData;
        const isCurrentPost = acknowledgmentId === id;

        if (isCurrentPost) {
          if (parentId) {
            dropChildCommentDataCommentList(
              acknowledgmentId,
              parentId,
              commentId,
            );
            dropChildCommentDataChildCommentList(parentId, commentId);
            dropChildLastCommentDataAcknowledgementList(
              acknowledgmentId,
              parentId,
              commentId,
            );
          } else if (isCommentInData(acknowledgmentId, commentId)) {
            dropLastCommentDataAcknowledgementList(acknowledgmentId, commentId);
            dropCommentDataCommentList(acknowledgmentId, commentId);
            dropCommentDataChildCommentList(commentId);
            decreaseAcknowledgementCommentAmount(acknowledgmentId);
          }
        }
      },

      // Add reaction to comment
      addCommentReaction: (reaction: AcknowledgementCommentReactionSocket) => {
        const { emoji, unified, userId, commentId, postId, parentId } =
          reaction;

        if (parentId) {
          updateReactionChildComment(id, parentId, commentId, reactions =>
            addReaction(reactions, emoji, unified, userId === user?.id),
          );
        } else {
          updateReactionComment(postId, commentId, reactions =>
            addReaction(reactions, emoji, unified, userId === user?.id),
          );
        }
      },

      // Remove reaction from comment
      removeCommentReaction: (
        reaction: AcknowledgementCommentReactionSocket,
      ) => {
        const { emoji, userId, commentId, postId, parentId } = reaction;

        if (parentId) {
          updateReactionChildComment(id, parentId, commentId, reactions =>
            removeReaction(reactions, emoji, userId === user?.id),
          );
        } else {
          updateReactionComment(postId, commentId, reactions =>
            removeReaction(reactions, emoji, userId === user?.id),
          );
        }
      },
    };

    // Map of event names to their handlers
    const eventSubscriptions = {
      [ACKNOWLEDGEMENT_COMMENT_CREATED]: eventHandlers.createCommentPost,
      [ACKNOWLEDGEMENT_COMMENT_UPDATED]: eventHandlers.updateCommentPost,
      [ACKNOWLEDGEMENT_COMMENT_DELETED]: eventHandlers.deleteCommentPost,
      [NEW_POST_COMMENT_REACTION]: eventHandlers.addCommentReaction,
      [REMOVE_POST_COMMENT_REACTION]: eventHandlers.removeCommentReaction,
    };

    // Subscribe to all events
    Object.entries(eventSubscriptions).forEach(([event, handler]) => {
      socket.listenEvent(event, handler);
    });

    // Cleanup function to unsubscribe from all events
    return () => {
      Object.entries(eventSubscriptions).forEach(([event, handler]) => {
        socket.closeEvent(event, handler);
      });
    };
  }, [socket, openViewComments, openSendComment]);
};

export default useAcknowledgementCommentsSocket;
