import { AxiosResponse } from 'axios';

import { queryClient } from 'src/config/react-query';
import { Comment } from 'src/types/comments';
import { DEFAULT_EMOJI } from 'src/types/feed';
import {
  MarketplacePost,
  MarketplaceNotificationsResponse,
} from 'src/types/marketplace';
import { DataUpdate, Updater } from 'src/types/queries';
import { Reaction } from 'src/types/reaction';
import { findIndexOnPages } from 'src/utils/pages';
import { functionalUpdate } from 'src/utils/queries';
import { sortReactions } from 'src/utils/reactions';

import { invalidateReactionUserList } from 'src/components/dashboard/reactions/queries';

export const marketplaceKeys = {
  all: () => ['marketplace posts'],
  list: () => [...marketplaceKeys.all(), 'list'],
  mine: () => [...marketplaceKeys.all(), 'mine'],
  mineCount: () => [...marketplaceKeys.all(), 'mine count'],
  allDetail: () => [...marketplaceKeys.all(), 'detail'],
  detail: (id: number | string) => [...marketplaceKeys.allDetail(), Number(id)],
  comment: {
    all: () => [...marketplaceKeys.all(), 'comment'],
    list: () => [...marketplaceKeys.comment.all(), 'list'],
    detail: (id: number | string) => [
      ...marketplaceKeys.comment.list(),
      Number(id),
    ],
  },
  childComment: {
    all: () => [...marketplaceKeys.all(), 'childComment'],
    list: () => [...marketplaceKeys.childComment.all(), 'list'],
    detail: (id: number | string) => [
      ...marketplaceKeys.childComment.list(),
      Number(id),
    ],
  },
  notifications: {
    all: () => [...marketplaceKeys.all(), 'notifications'],
    module: () => [...marketplaceKeys.notifications.all(), 'module'],
  },
};

const commentUpdater = (oldComment: DataUpdate<Comment>, comment: Comment) => {
  if (!oldComment) return oldComment;
  oldComment.body = comment.body;
  oldComment.bodyAttributes = comment.bodyAttributes;
  oldComment.attachments = comment.attachments;
  oldComment.updatedAt = comment.updatedAt;
  return oldComment;
};

/**
 * Safely retrieves and initializes `post.lastComments` for in-place updates
 * inside React Query cache updaters.
 */
const getMutableLastComments = (post: MarketplacePost) => {
  if (!Array.isArray(post.lastComments)) {
    post.lastComments = [];
  }

  return post.lastComments;
};

export const dropMarketplaceListData = (postId: number) => {
  queryClient.setQueryData(marketplaceKeys.list(), (oldData: any): any => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findIndexOnPages(
      oldData.pages,
      (post: any) => post.id === postId,
    );

    if (pageIndex !== -1 && postIndex !== -1) {
      oldData.pages[pageIndex].data.splice(postIndex, 1);
    }

    return oldData;
  });
};

export const pushMarketplaceListData = (postItem: MarketplacePost) => {
  queryClient.setQueryData(marketplaceKeys.list(), (oldData: any): any => {
    if (!oldData) return oldData;

    oldData.pages[0].data.splice(0, 0, postItem);

    return oldData;
  });
};

export const setMarketplaceListData = (
  postId: number,
  updater: Updater<MarketplacePost>,
) => {
  queryClient.setQueryData(marketplaceKeys.list(), (oldData: any): any => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findIndexOnPages(
      oldData.pages,
      (post: any) => post.id === postId,
    );

    if (pageIndex !== -1 && postIndex !== -1) {
      oldData.pages[pageIndex].data[postIndex] = functionalUpdate(
        updater,
        oldData.pages[pageIndex].data[postIndex],
      );
    }

    return oldData;
  });
};

export const setMyMarketplaceListData = (
  postId: number,
  updater: Updater<MarketplacePost>,
) => {
  queryClient.setQueryData(marketplaceKeys.mine(), (oldData: any): any => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findIndexOnPages(
      oldData.pages,
      (post: any) => post.id === postId,
    );

    if (pageIndex !== -1 && postIndex !== -1) {
      oldData.pages[pageIndex].data[postIndex] = functionalUpdate(
        updater,
        oldData.pages[pageIndex].data[postIndex],
      );
    }

    return oldData;
  });
};

export const setMarketplaceDetailData = (
  postId: number,
  updater: Updater<MarketplacePost>,
) => {
  queryClient.setQueryData<AxiosResponse<MarketplacePost> | undefined>(
    marketplaceKeys.detail(postId),
    oldData => {
      if (!oldData) return oldData;

      oldData.data = functionalUpdate(updater, oldData.data);

      return oldData;
    },
  );
};

// COMMENTS
export const increaseMarketplacePostCommentAmount = (postId: number) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return;

    return { ...oldPost, commentCount: oldPost.commentCount + 1 };
  });
};

export const decreaseMarketplacePostCommentAmount = (postId: number) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return;

    return { ...oldPost, commentCount: Math.max(oldPost.commentCount - 1, 0) };
  });
};

export const dropCommentMyMarketplaceList = (
  postId: number,
  commentId: number,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments.splice(commentIndex, 1);
    }

    return oldPost;
  });
};

export const dropCommentMarketplaceList = (
  postId: number,
  commentId: number,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments.splice(commentIndex, 1);
    }

    return oldPost;
  });
};

export const dropCommentMarketplaceDetail = (
  postId: number,
  commentId: number,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments.splice(commentIndex, 1);
    }

    return oldPost;
  });
};

export const dropCommentDataCommentList = (
  postId: number,
  commentId: number,
) => {
  queryClient.setQueryData(
    marketplaceKeys.comment.detail(postId),
    (oldData: any) => {
      if (!oldData?.pages) return oldData;

      const [pageIndex, commentIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        comment => comment.id === commentId,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        const newPages = [...oldData.pages];
        newPages[pageIndex] = {
          ...newPages[pageIndex],
          data: newPages[pageIndex].data.filter(
            (comment: Comment) => comment.id !== commentId,
          ),
        };
        return { ...oldData, pages: newPages };
      }

      return oldData;
    },
  );
};

export const dropCommentDataChildCommentList = (commentId: number) => {
  queryClient.removeQueries(marketplaceKeys.childComment.detail(commentId));
};

// Add new comment to lastComments - Marketplace List
export const unshiftLastCommentDataMarketplaceList = (
  postId: number,
  comment: Comment,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    getMutableLastComments(oldPost).unshift(comment);

    return oldPost;
  });
};

// Add new comment to lastComments - My Marketplace List
export const unshiftLastCommentDataMyMarketplaceList = (
  postId: number,
  comment: Comment,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    getMutableLastComments(oldPost).unshift(comment);

    return oldPost;
  });
};

// Add new comment to lastComments - Marketplace Post Detail
export const unshiftLastCommentDataMarketplacePostDetail = (
  postId: number,
  comment: Comment,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;

    getMutableLastComments(oldPost).unshift(comment);

    return oldPost;
  });
};

export const unshiftChildLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  childComment: Comment,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      if (!oldPost.lastComments[commentIndex].children) {
        oldPost.lastComments[commentIndex].children = [];
      }

      oldPost.lastComments[commentIndex].children.unshift(childComment);
    }

    return oldPost;
  });
};

export const unshiftChildLastCommentDataMyMarketplaceList = (
  postId: number,
  commentId: number,
  childComment: Comment,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      if (!oldPost.lastComments[commentIndex].children) {
        oldPost.lastComments[commentIndex].children = [];
      }

      oldPost.lastComments[commentIndex].children.unshift(childComment);
    }

    return oldPost;
  });
};

export const unshiftChildLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  childComment: Comment,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      if (!oldPost.lastComments[commentIndex].children) {
        oldPost.lastComments[commentIndex].children = [];
      }

      oldPost.lastComments[commentIndex].children.unshift(childComment);
    }

    return oldPost;
  });
};

export const pushChildCommentDataCommentList = (
  postId: number,
  commentId: number,
  childComment: Comment,
) => {
  queryClient.setQueryData(
    marketplaceKeys.comment.detail(postId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, commentIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        comment => comment.id === commentId,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        if (!oldData.pages[pageIndex].data[commentIndex].children) {
          oldData.pages[pageIndex].data[commentIndex].children = [];
        }

        oldData.pages[pageIndex].data[commentIndex].children.push(childComment);
      }

      return oldData;
    },
  );
};

export const pushChildCommentDataChildCommentList = (
  commentId: number,
  childComment: Comment,
) => {
  queryClient.setQueryData(
    marketplaceKeys.childComment.detail(commentId),
    (oldData: any) => {
      if (!oldData) return oldData;

      oldData.pages[0].data.push(childComment);

      return oldData;
    },
  );
};

export const setChildLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Comment>,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        oldPost.lastComments[commentIndex].children[childIndex] =
          functionalUpdate(
            updater,
            oldPost.lastComments[commentIndex].children[childIndex],
          );
      }
    }

    return oldPost;
  });
};

export const setChildLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Comment>,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        oldPost.lastComments[commentIndex].children[childIndex] =
          functionalUpdate(
            updater,
            oldPost.lastComments[commentIndex].children[childIndex],
          );
      }
    }

    return oldPost;
  });
};

export const setChildCommentDataCommentList = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Comment>,
) => {
  queryClient.setQueryData(
    marketplaceKeys.comment.detail(postId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, commentIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        comment => comment.id === commentId,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        const childIndex = oldData.pages[pageIndex].data[
          commentIndex
        ].children.findIndex((child: Comment) => child.id === childId);

        if (childIndex !== -1) {
          oldData.pages[pageIndex].data[commentIndex].children[childIndex] =
            functionalUpdate(
              updater,
              oldData.pages[pageIndex].data[commentIndex].children[childIndex],
            );
        }
      }

      return oldData;
    },
  );
};

export const setChildCommentDataChildCommentList = (
  commentId: number,
  childId: number,
  updater: Updater<Comment>,
) => {
  queryClient.setQueryData(
    marketplaceKeys.childComment.detail(commentId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, childIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        child => child.id === childId,
      );

      if (pageIndex !== -1 && childIndex !== -1) {
        oldData.pages[pageIndex].data[childIndex] = functionalUpdate(
          updater,
          oldData.pages[pageIndex].data[childIndex],
        );
      }

      return oldData;
    },
  );
};

// Update comment in lastComments - Marketplace List
export const updateLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  updater: Updater<Comment>,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = functionalUpdate(
        updater,
        oldPost.lastComments[commentIndex],
      );
    }

    return oldPost;
  });
};

// Update comment in lastComments - My Marketplace List
export const updateLastCommentDataMyMarketplaceList = (
  postId: number,
  commentId: number,
  updater: Updater<Comment>,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = functionalUpdate(
        updater,
        oldPost.lastComments[commentIndex],
      );
    }

    return oldPost;
  });
};

// Update comment in lastComments - Marketplace Post Detail
export const updateLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  updater: Updater<Comment>,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = functionalUpdate(
        updater,
        oldPost.lastComments[commentIndex],
      );
    }

    return oldPost;
  });
};

// Update comment in paginated comment list
export const updateCommentDataCommentList = (
  postId: number,
  commentId: number,
  comment: Comment,
) => {
  const updater = (oldComment: DataUpdate<Comment>) =>
    commentUpdater(oldComment, comment);
  setCommentDataCommentList(postId, commentId, updater);
};

// Main function to update comment across all views
export const updateCommentData = (
  postId: number,
  commentId: number,
  comment: Comment,
) => {
  const updater = (oldComment: DataUpdate<Comment>) =>
    commentUpdater(oldComment, comment);
  updateLastCommentDataMarketplaceList(postId, commentId, updater);
  updateLastCommentDataMyMarketplaceList(postId, commentId, updater);
  updateLastCommentDataMarketplacePostDetail(postId, commentId, updater);
  updateCommentDataCommentList(postId, commentId, comment);
};

export const updateChildCommentData = (
  postId: number,
  parentId: number,
  childId: number,
  comment: Comment,
) => {
  const updater = (oldComment: DataUpdate<Comment>) =>
    commentUpdater(oldComment, comment);
  setChildLastCommentDataMarketplaceList(postId, parentId, childId, updater);
  setChildLastCommentDataMarketplacePostDetail(
    postId,
    parentId,
    childId,
    updater,
  );
  setChildCommentDataCommentList(postId, parentId, childId, updater);
  setChildCommentDataChildCommentList(parentId, childId, updater);
};

const reactionCommentUpdater = (
  oldComment: Comment,
  updater: Updater<Reaction[]>,
) => {
  if (!oldComment) return oldComment;

  oldComment.reactions = functionalUpdate(updater, oldComment.reactions);

  sortReactions(oldComment.reactions, DEFAULT_EMOJI.emoji);

  return oldComment;
};

export const setCommentDataCommentList = (
  postId: number,
  commentId: number,
  updater: Updater<Comment>,
) => {
  queryClient.setQueryData(
    marketplaceKeys.comment.detail(postId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, commentIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        comment => comment.id === commentId,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        oldData.pages[pageIndex].data[commentIndex] = functionalUpdate(
          updater,
          oldData.pages[pageIndex].data[commentIndex],
        );
      }

      return oldData;
    },
  );
};

export const updateReactionLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  updater: Updater<Reaction[]>,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = reactionCommentUpdater(
        oldPost.lastComments[commentIndex],
        updater,
      );
    }

    return oldPost;
  });
};

// Update parent comment reactions in lastComments - My Marketplace List
export const updateReactionLastCommentDataMyMarketplaceList = (
  postId: number,
  commentId: number,
  updater: Updater<Reaction[]>,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = reactionCommentUpdater(
        oldPost.lastComments[commentIndex],
        updater,
      );
    }

    return oldPost;
  });
};

// Update parent comment reactions in lastComments - Marketplace Post Detail
export const updateReactionLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  updater: Updater<Reaction[]>,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1) {
      oldPost.lastComments[commentIndex] = reactionCommentUpdater(
        oldPost.lastComments[commentIndex],
        updater,
      );
    }

    return oldPost;
  });
};

// Update parent comment reactions in paginated comment list
export const updateReactionCommentDataCommentList = (
  postId: number,
  commentId: number,
  updater: Updater<Reaction[]>,
) => {
  setCommentDataCommentList(postId, commentId, oldComment => {
    if (!oldComment) return oldComment;
    return reactionCommentUpdater(oldComment, updater);
  });
};

// Main function to update parent comment reactions across all views
export const updateReactionCommentData = (
  postId: number,
  commentId: number,
  updater: Updater<Reaction[]>,
) => {
  updateReactionLastCommentDataMarketplaceList(postId, commentId, updater);
  updateReactionLastCommentDataMyMarketplaceList(postId, commentId, updater);
  updateReactionLastCommentDataMarketplacePostDetail(
    postId,
    commentId,
    updater,
  );
  updateReactionCommentDataCommentList(postId, commentId, updater);
};

export const updateReactionChildLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  setChildLastCommentDataMarketplaceList(
    postId,
    commentId,
    childId,
    oldChild => {
      if (!oldChild) return oldChild;

      oldChild.reactions = functionalUpdate(updater, oldChild.reactions);

      sortReactions(oldChild.reactions, DEFAULT_EMOJI.emoji);

      return oldChild;
    },
  );
};

export const updateReactionChildLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  setChildLastCommentDataMarketplacePostDetail(
    postId,
    commentId,
    childId,
    oldChild => {
      if (!oldChild) return oldChild;

      oldChild.reactions = functionalUpdate(updater, oldChild.reactions);

      sortReactions(oldChild.reactions, DEFAULT_EMOJI.emoji);

      return oldChild;
    },
  );
};

export const updateReactionChildLastCommentDataMyMarketplaceList = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        const child = oldPost.lastComments[commentIndex].children[childIndex];
        child.reactions = functionalUpdate(updater, child.reactions);
        sortReactions(child.reactions, DEFAULT_EMOJI.emoji);
      }
    }

    return oldPost;
  });
};

export const updateReactionChildCommentDataCommentList = (
  postId: number,
  commentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  setChildCommentDataCommentList(postId, commentId, childId, oldChild => {
    if (!oldChild) return oldChild;

    oldChild.reactions = functionalUpdate(updater, oldChild.reactions);

    sortReactions(oldChild.reactions, DEFAULT_EMOJI.emoji);

    return oldChild;
  });
};

export const updateReactionChildCommentDataChildCommentList = (
  commentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  setChildCommentDataChildCommentList(commentId, childId, oldChild => {
    if (!oldChild) return oldChild;

    oldChild.reactions = functionalUpdate(updater, oldChild.reactions);

    sortReactions(oldChild.reactions, DEFAULT_EMOJI.emoji);

    return oldChild;
  });
};

// Main function to update child comment reactions across all views
export const updateReactionChildCommentData = (
  postId: number,
  parentId: number,
  childId: number,
  updater: Updater<Reaction[]>,
) => {
  updateReactionChildLastCommentDataMarketplaceList(
    postId,
    parentId,
    childId,
    updater,
  );
  updateReactionChildLastCommentDataMyMarketplaceList(
    postId,
    parentId,
    childId,
    updater,
  );
  updateReactionChildLastCommentDataMarketplacePostDetail(
    postId,
    parentId,
    childId,
    updater,
  );
  updateReactionChildCommentDataCommentList(postId, parentId, childId, updater);
  updateReactionChildCommentDataChildCommentList(parentId, childId, updater);
};

export const dropChildLastCommentDataMyMarketplaceList = (
  postId: number,
  commentId: number,
  childId: number,
) => {
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost?.lastComments) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        oldPost.lastComments[commentIndex].children.splice(childIndex, 1);
      }
    }

    return oldPost;
  });
};

export const dropChildLastCommentDataMarketplaceList = (
  postId: number,
  commentId: number,
  childId: number,
) => {
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        oldPost.lastComments[commentIndex].children.splice(childIndex, 1);
      }
    }

    return oldPost;
  });
};

export const dropChildLastCommentDataMarketplacePostDetail = (
  postId: number,
  commentId: number,
  childId: number,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;

    const commentIndex = oldPost.lastComments.findIndex(
      comment => comment.id === commentId,
    );

    if (commentIndex !== -1 && oldPost.lastComments[commentIndex].children) {
      const childIndex = oldPost.lastComments[commentIndex].children.findIndex(
        (child: Comment) => child.id === childId,
      );

      if (childIndex !== -1) {
        oldPost.lastComments[commentIndex].children.splice(childIndex, 1);
      }
    }

    return oldPost;
  });
};

export const dropChildCommentDataCommentList = (
  postId: number,
  commentId: number,
  childId: number,
) => {
  queryClient.setQueryData(
    marketplaceKeys.comment.detail(postId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, commentIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        comment => comment.id === commentId,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        const childIndex = oldData.pages[pageIndex].data[
          commentIndex
        ].children.findIndex((child: Comment) => child.id === childId);

        if (childIndex !== -1) {
          oldData.pages[pageIndex].data[commentIndex].children.splice(
            childIndex,
            1,
          );
        }
      }

      return oldData;
    },
  );
};

export const dropChildCommentDataChildCommentList = (
  commentId: number,
  childId: number,
) => {
  queryClient.setQueryData(
    marketplaceKeys.childComment.detail(commentId),
    (oldData: any) => {
      if (!oldData) return oldData;

      const [pageIndex, childIndex] = findIndexOnPages<Comment>(
        oldData.pages,
        child => child.id === childId,
      );

      if (pageIndex !== -1 && childIndex !== -1) {
        oldData.pages[pageIndex].data.splice(childIndex, 1);
      }

      return oldData;
    },
  );
};

// REACTIONS
const reactionUpdater = (
  oldPost: MarketplacePost,
  updater: Updater<Reaction[]>,
) => {
  if (!oldPost) return oldPost;

  oldPost.reactions = functionalUpdate(updater, oldPost.reactions);

  sortReactions(oldPost.reactions, DEFAULT_EMOJI.emoji);

  return oldPost;
};

export const updateMarketplacePostReaction = (
  postId: number,
  emoji: string,
  updater: Updater<Reaction[]>,
) => {
  setMarketplaceDetailData(postId, oldPost => {
    if (!oldPost) return oldPost;
    return reactionUpdater(oldPost, updater);
  });
  setMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;
    return reactionUpdater(oldPost, updater);
  });
  setMyMarketplaceListData(postId, oldPost => {
    if (!oldPost) return oldPost;
    return reactionUpdater(oldPost, updater);
  });

  invalidateReactionUserList(postId, emoji);
};

// NOTIFICATIONS
export const addMarketplaceNotification = (count: number = 1) => {
  queryClient.setQueryData<
    AxiosResponse<MarketplaceNotificationsResponse> | undefined
  >(marketplaceKeys.notifications.module(), oldData => {
    if (!oldData?.data) return oldData;

    oldData.data.marketplaceNotifications += count;

    return oldData;
  });
};

export const removeMarketplaceNotification = (count: number = 1) => {
  queryClient.setQueryData<
    AxiosResponse<MarketplaceNotificationsResponse> | undefined
  >(marketplaceKeys.notifications.module(), oldData => {
    if (!oldData?.data) return oldData;

    oldData.data.marketplaceNotifications -= count;

    return oldData;
  });
};

export const clearMarketplaceNotifications = () => {
  queryClient.setQueryData<
    AxiosResponse<MarketplaceNotificationsResponse> | undefined
  >(marketplaceKeys.notifications.module(), oldData => {
    if (!oldData?.data) return oldData;

    oldData.data.marketplaceNotifications = 0;

    return oldData;
  });
};
