import { InfiniteData } from 'react-query';

import { AxiosResponse } from 'axios';

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

export const pushLastCommentData = (postId: number, commentItem: Comment) => {
  queryClient.setQueryData<
    InfiniteData<AxiosResponse<MarketplacePost[]>> | undefined
  >(marketplaceKeys.list(), oldData => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findPostIndexOnPages(postId, oldData.pages);

    if (pageIndex !== -1 && postIndex !== -1) {
      if (oldData.pages[pageIndex].data[postIndex].lastComments) {
        oldData.pages[pageIndex].data[postIndex].lastComments.unshift(
          commentItem,
        );
      } else {
        oldData.pages[pageIndex].data[postIndex].lastComments = [];
        oldData.pages[pageIndex].data[postIndex].lastComments.push(commentItem);
      }
    }

    return oldData;
  });
};

export const pushLastCommentDataDetail = (
  postId: number,
  commentItem: Comment,
) => {
  queryClient.setQueryData<AxiosResponse<MarketplacePost> | undefined>(
    marketplaceKeys.detail(postId),
    oldData => {
      if (!oldData?.data) return oldData;

      if (oldData.data.lastComments) {
        oldData.data.lastComments.unshift(commentItem);
      } else {
        oldData.data.lastComments = [];
        oldData.data.lastComments.push(commentItem);
      }

      return oldData;
    },
  );
};

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

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

  sortReactions(oldComment.reactions, DEFAULT_EMOJI.emoji);

  return oldComment;
};

export const setCommentListDataPaginated = (
  postItemId: number,
  commentItemId: number,
  updater: Updater<Comment>,
) => {
  queryClient.setQueryData<InfiniteData<AxiosResponse<Comment[]>> | undefined>(
    marketplaceKeys.comment.detail(postItemId),
    oldData => {
      if (!oldData) return oldData;

      const [pageIndex, chatIndex] = findPostIndexOnPages(
        commentItemId,
        oldData.pages,
      );

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

      return oldData;
    },
  );
};

export const addCommentListDataReactionPaginated = (
  postItemId: number,
  commentItemId: number,
  emoji: string,
  unified: string,
  isLoggedUserReaction: boolean = true,
) => {
  setCommentListDataPaginated(postItemId, commentItemId, oldComment => {
    return reactionUpdater(oldComment, reactions =>
      addReaction(reactions, emoji, unified, isLoggedUserReaction),
    );
  });
};

export const removeCommentListDataReactionPaginated = (
  postItemId: number,
  commentItemId: number,
  emoji: string,
  isLoggedUserReaction: boolean = true,
) => {
  setCommentListDataPaginated(postItemId, commentItemId, oldComment => {
    return reactionUpdater(oldComment, reactions =>
      removeReaction(reactions, emoji, isLoggedUserReaction),
    );
  });
};

export const addLastCommentListDataReaction = (
  postId: number,
  commentId: number,
  emoji: string,
  unified: string,
  queryKey: any,
  isLoggedUserReaction: boolean = true,
) => {
  queryClient.setQueryData<
    InfiniteData<AxiosResponse<MarketplacePost[]>> | undefined
  >(queryKey.list(), oldData => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findPostIndexOnPages(postId, oldData.pages);

    if (pageIndex !== -1 && postIndex !== -1) {
      const indexAux = oldData.pages[pageIndex].data[
        postIndex
      ].lastComments?.findIndex((elem: Comment) => elem.id === commentId);
      oldData.pages[pageIndex].data[postIndex].lastComments[
        indexAux
      ].reactions = addReaction(
        oldData.pages[pageIndex].data[postIndex].lastComments[indexAux]
          .reactions,
        emoji,
        unified,
        isLoggedUserReaction,
      );
      sortReactions(
        oldData.pages[pageIndex].data[postIndex].lastComments[indexAux]
          .reactions,
        DEFAULT_EMOJI.emoji,
      );
    }

    return oldData;
  });
};

export const removeLastCommentListDataReaction = (
  postId: number,
  commentId: number,
  emoji: string,
  queryKey: any,
  isLoggedUserReaction: boolean = true,
) => {
  queryClient.setQueryData<
    InfiniteData<AxiosResponse<MarketplacePost[]>> | undefined
  >(queryKey.list(), oldData => {
    if (!oldData) return oldData;

    const [pageIndex, postIndex] = findPostIndexOnPages(postId, oldData.pages);

    if (pageIndex !== -1 && postIndex !== -1) {
      const indexAux = oldData.pages[pageIndex].data[
        postIndex
      ].lastComments?.findIndex((elem: Comment) => elem.id === commentId);
      oldData.pages[pageIndex].data[postIndex].lastComments[
        indexAux
      ].reactions = removeReaction(
        oldData.pages[pageIndex].data[postIndex].lastComments[indexAux]
          .reactions,
        emoji,
        isLoggedUserReaction,
      );
      sortReactions(
        oldData.pages[pageIndex].data[postIndex].lastComments[indexAux]
          .reactions,
        DEFAULT_EMOJI.emoji,
      );
    }

    return oldData;
  });
};

export const addLastCommentListDataReactionDetail = (
  postId: number,
  commentId: number,
  emoji: string,
  unified: string,
  isLoggedUserReaction: boolean = true,
) => {
  queryClient.setQueryData<AxiosResponse<MarketplacePost> | undefined>(
    marketplaceKeys.detail(postId),
    oldData => {
      if (!oldData?.data) return oldData;

      const indexAux = oldData.data.lastComments?.findIndex(
        (elem: Comment) => elem.id === commentId,
      );

      oldData.data.lastComments[indexAux].reactions = addReaction(
        oldData.data.lastComments[indexAux].reactions,
        emoji,
        unified,
        isLoggedUserReaction,
      );

      sortReactions(
        oldData.data.lastComments[indexAux].reactions,
        DEFAULT_EMOJI.emoji,
      );

      return oldData;
    },
  );
};

export const removeLastCommentListDataReactionDetail = (
  postId: number,
  commentId: number,
  emoji: string,
  isLoggedUserReaction: boolean = true,
) => {
  queryClient.setQueryData<AxiosResponse<MarketplacePost> | undefined>(
    marketplaceKeys.detail(postId),
    oldData => {
      if (!oldData?.data) return oldData;

      const indexAux = oldData.data.lastComments?.findIndex(
        (elem: Comment) => elem.id === commentId,
      );

      oldData.data.lastComments[indexAux].reactions = removeReaction(
        oldData.data.lastComments[indexAux].reactions,
        emoji,
        isLoggedUserReaction,
      );

      sortReactions(
        oldData.data.lastComments[indexAux].reactions,
        DEFAULT_EMOJI.emoji,
      );

      return oldData;
    },
  );
};

export const updateCommentListData = (
  parentId: number,
  childId: number,
  commentBody: string,
  commentAttachments: any[],
  bodyAttributes: any,
) => {
  queryClient.setQueryData<InfiniteData<AxiosResponse<Comment[]>> | undefined>(
    marketplaceKeys.comment.detail(parentId),
    oldData => {
      if (!oldData) return oldData;

      const [pageIndex, commentIndex] = findPostIndexOnPages(
        childId,
        oldData.pages,
      );

      if (pageIndex !== -1 && commentIndex !== -1) {
        oldData.pages[pageIndex].data[commentIndex].bodyAttributes =
          bodyAttributes;
        oldData.pages[pageIndex].data[commentIndex].body = commentBody;
        oldData.pages[pageIndex].data[commentIndex].attachments =
          commentAttachments;
      }

      return oldData;
    },
  );
};

export const updateLastCommentDataDetail = (
  postId: number,
  commentId: number,
  commentBody: string,
  commentAttachments: any[],
  bodyAttributes: any,
) => {
  queryClient.setQueryData<AxiosResponse<MarketplacePost> | undefined>(
    marketplaceKeys.detail(postId),
    oldData => {
      if (!oldData) return oldData;

      const indexAux = oldData.data.lastComments?.findIndex(
        (elem: Comment) => elem.id === commentId,
      );

      oldData.data.lastComments[indexAux].body = commentBody;
      oldData.data.lastComments[indexAux].attachments = commentAttachments;
      oldData.data.lastComments[indexAux].bodyAttributes = bodyAttributes;

      return oldData;
    },
  );
};

export const updateLastCommentData = (
  postId: number,
  commentId: number,
  commentBody: string,
  commentAttachments: any[],
  bodyAttributes: any,
) => {
  queryClient.setQueryData<
    InfiniteData<AxiosResponse<MarketplacePost[]>> | undefined
  >(marketplaceKeys.list(), oldData => {
    if (!oldData) return oldData;
    const [pageIndex, postIndex] = findPostIndexOnPages(postId, oldData.pages);

    if (pageIndex !== -1 && postIndex !== -1) {
      const indexAux = oldData.pages[pageIndex].data[
        postIndex
      ].lastComments?.findIndex((elem: Comment) => elem.id === commentId);
      if (indexAux !== undefined && indexAux !== -1) {
        oldData.pages[pageIndex].data[postIndex].lastComments[indexAux].body =
          commentBody;
        oldData.pages[pageIndex].data[postIndex].lastComments[
          indexAux
        ].attachments = commentAttachments;
        oldData.pages[pageIndex].data[postIndex].lastComments[
          indexAux
        ].bodyAttributes = bodyAttributes;
      }
    }

    return oldData;
  });
};
