import { memo } from 'react';
import { useInfiniteQuery, useMutation } from 'react-query';
import { useNavigate } from 'react-router';

import { type AxiosResponse } from 'axios';
import SendIcon from '@material-hu/icons/material/Send';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuListItem from '@material-hu/components/design-system/List/components/ListItem';
import Pills from '@material-hu/components/design-system/Pills';

import { useAuth } from 'src/contexts/JWTContext';
import useGeneralError from 'src/hooks/useGeneralError';
import usePermissions from 'src/hooks/usePermissions';
import { useOpenConversation } from 'src/pages/dashboard/Conversations/hooks/useConversationsQueries';
import { createChat } from 'src/services/chats';
import { type GroupReactionUsersResponse } from 'src/types/groups';
import { type Reaction, type ReactionUsersResponse } from 'src/types/reaction';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { UserPermissions } from 'src/utils/permissions';
import { getFullName, getInitials } from 'src/utils/userUtils';

import { InfiniteList } from 'src/components/list';

import { chatRoutes } from '../../chat/routes';
import { reactionKeys } from '../queries';

import ReactionUsersListSkeleton from './ReactionUsersListSkeleton';

export type GenericGetReactionUsersFunction = (
  emoji: string,
  params?: {
    timestamp?: string;
    cursor?: string;
  },
) => Promise<AxiosResponse<ReactionUsersResponse | GroupReactionUsersResponse>>;

const { VIEW_REGULAR_CHATS, VIEW_CHATS_V2 } = UserPermissions;

type ReactionUsersListProps = {
  id: number;
  reaction: Reaction;
  getReactionUsers: GenericGetReactionUsersFunction;
};

const ReactionUsersList = ({
  id,
  reaction,
  getReactionUsers,
}: ReactionUsersListProps) => {
  const { user } = useAuth();
  const navigate = useNavigate();
  const { hasAll: canViewChats } = usePermissions([VIEW_REGULAR_CHATS]);
  const { hasAll: canViewConversations } = usePermissions([VIEW_CHATS_V2]);

  const { t } = useTranslation();
  const showGeneralError = useGeneralError();

  const {
    data,
    isLoading,
    fetchNextPage,
    isFetchingNextPage,
    hasNextPage,
    isSuccess,
  } = useInfiniteQuery(
    reactionKeys.user.dialogList(id, reaction?.emoji),
    ({ pageParam }) => {
      return getReactionUsers(reaction?.emoji, {
        timestamp: pageParam?.timestamp,
        cursor: pageParam?.cursor,
      });
    },
    {
      enabled: !!reaction?.emoji,
      getNextPageParam: lastPage => {
        if ('timestamp' in lastPage.data && lastPage.data.timestamp) {
          return { timestamp: lastPage.data.timestamp };
        }
        if ('cursor' in lastPage.data && lastPage.data.cursor) {
          return { cursor: lastPage.data.cursor };
        }
        return undefined;
      },
    },
  );

  const reactionUsers = data?.pages.flatMap(response => {
    if ('users' in response.data) {
      return response.data.users;
    }
    if ('items' in response.data) {
      return response.data.items;
    }
    return [];
  });

  const openConversationMutation = useOpenConversation();

  const chatMutation = useMutation((userId: number) => createChat(userId), {
    onSuccess: res => {
      const chatId = res.data.chatId;
      const state = res.data;
      navigate(chatRoutes.thread.detail(chatId), { state });
    },
    onError: error => {
      showGeneralError(error, t('CHAT:ERROR_CREATING_CHAT'));
    },
  });

  const handleOpenConversation = async (userId: number) => {
    if (canViewConversations) {
      openConversationMutation.mutateAsync({ users: [userId.toString()] });
    } else {
      chatMutation.mutateAsync(userId);
    }
  };

  return (
    <InfiniteList
      isLoading={isLoading}
      fetchNextPage={fetchNextPage}
      isFetchingNextPage={isFetchingNextPage}
      totalPages={data?.pages.length}
      isSuccess={isSuccess}
      isEmpty={!reactionUsers?.length}
      hasNextPage={hasNextPage}
      customLoader={<ReactionUsersListSkeleton />}
    >
      {reactionUsers?.map(reactionUser => {
        const showChatButton = user?.id !== reactionUser.id && canViewChats;
        return (
          <div key={reactionUser.id}>
            <HuListItem
              slotProps={{
                container: {
                  sx: { py: 1.5, pl: 0 },
                },
              }}
              avatar={{
                src: reactionUser.profilePicture ?? undefined,
                text: getInitials(getFullName(reactionUser)),
                alt: getFullName(reactionUser),
              }}
              text={{ title: getFullName(reactionUser) }}
              sideContent={
                <>
                  {reactionUser.isExternal && (
                    <Pills
                      label={t('group:external')}
                      type="neutral"
                      size="small"
                      hasIcon={false}
                    />
                  )}
                  {showChatButton && (
                    <Button
                      variant="outlined"
                      endIcon={
                        <SendIcon sx={{ width: 13, height: 13, ml: 0.5 }} />
                      }
                      onClick={() => handleOpenConversation(reactionUser.id)}
                    >
                      {t('CHAT:SEND_MESSAGE')}
                    </Button>
                  )}
                </>
              }
            />
          </div>
        );
      })}
    </InfiniteList>
  );
};

export default memo(ReactionUsersList);
