import { useEffect } from 'react';
import { useInfiniteQuery } from 'react-query';
import { useNavigate } from 'react-router';

import Stack from '@material-hu/mui/Stack';

import StateCard from '@material-hu/components/design-system/StateCard';

import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useRequiredAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import useGeneralError from 'src/hooks/useGeneralError';
import usePermissions from 'src/hooks/usePermissions';
import { feedRoutes } from 'src/pages/dashboard/feed/routes';
import {
  addUserFeedListDataReaction,
  profileKeys,
  removeUserFeedListDataReaction,
} from 'src/pages/dashboard/profile/queries';
import { getUserPostList } from 'src/services/users';
import { type PostReactionSocket } from 'src/types/posts';
import { type UserProfile } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { UserPermissions } from 'src/utils/permissions';

import InfiniteList from 'src/components/list/InfiniteList';
import PostCard from 'src/components/post/PostCard';

type FeedTabProps = {
  user: UserProfile;
};

export const FeedTab = ({ user: { id } }: FeedTabProps) => {
  const { t } = useLokaliseTranslation(['profile', 'post']);
  const showGeneralError = useGeneralError();
  const navigate = useNavigate();
  const socket = useSocket();
  const { user: loggedUser } = useRequiredAuth();
  const { hasAll: canPublishToFeed } = usePermissions([
    UserPermissions.CREATE_POSTS,
  ]);

  const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useInfiniteQuery(
      profileKeys.feed.list(id),
      ({ pageParam = '' }) => getUserPostList(id, pageParam),
      {
        getNextPageParam: lastPage =>
          lastPage.data?.length > 0
            ? lastPage.data[lastPage.data.length - 1].createdAt
            : undefined,
        onError: err => showGeneralError(err, t('post:error_loading_posts')),
      },
    );

  useEffect(() => {
    const addPostReaction = (reaction: PostReactionSocket) => {
      const { emoji, unified, userId, postId } = reaction;

      addUserFeedListDataReaction(
        id,
        postId,
        emoji,
        unified,
        userId === loggedUser.id,
      );
    };

    const removePostReaction = (reaction: PostReactionSocket) => {
      const { emoji, userId, postId } = reaction;

      removeUserFeedListDataReaction(
        id,
        postId,
        emoji,
        userId === loggedUser.id,
      );
    };

    socket.listenEvent(EVENTS_SOCKETS.NEW_POST_REACTION, addPostReaction);

    socket.listenEvent(EVENTS_SOCKETS.REMOVE_POST_REACTION, removePostReaction);

    return () => {
      socket.closeEvent(EVENTS_SOCKETS.NEW_POST_REACTION, addPostReaction);

      socket.closeEvent(
        EVENTS_SOCKETS.REMOVE_POST_REACTION,
        removePostReaction,
      );
    };
  }, [socket, loggedUser, id]);

  const handleAddReaction = (postId: number, emoji: string, unified: string) =>
    addUserFeedListDataReaction(id, postId, emoji, unified);

  const handleRemoveReaction = (postId: number, emoji: string) =>
    removeUserFeedListDataReaction(id, postId, emoji);

  const posts = data?.pages?.flatMap(page => page.data) || [];

  if (data && !posts.length) {
    return (
      <StateCard
        title={t('empty_state.title.posts')}
        description={t('empty_state.description.posts')}
        {...(canPublishToFeed && {
          primaryAction: {
            label: t('general:publish'),
            onClick: () => navigate(feedRoutes.feed()),
          },
        })}
      />
    );
  }

  return (
    <InfiniteList
      isSuccess={!!data}
      isLoading={isLoading}
      fetchNextPage={fetchNextPage}
      hasNextPage={hasNextPage}
      isFetchingNextPage={isFetchingNextPage}
    >
      {posts?.map(post => (
        <Stack
          key={post.id}
          sx={{ mb: 3 }}
        >
          <PostCard
            key={post.id}
            onAddReaction={handleAddReaction}
            onRemoveReaction={handleRemoveReaction}
            post={post}
          />
        </Stack>
      ))}
    </InfiniteList>
  );
};

export default FeedTab;
