import { ReactNode, useState } from 'react';
import { useQuery } from 'react-query';

import { Emoji } from 'emoji-picker-react';

import { PopperProps } from '@material-hu/mui/Popper';
import Stack from '@material-hu/mui/Stack';
import Tooltip from '@material-hu/mui/Tooltip';
import Typography from '@material-hu/mui/Typography';
import useMediaQuery from '@material-hu/mui/useMediaQuery';

import { Reaction as ReactionType } from 'src/types/reaction';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getReactionList } from 'src/utils/reactions';
import { getFullName } from 'src/utils/userUtils';

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

import { GenericGetReactionUsersFunction } from './UsersListDrawer/ReactionUsersList';

export type ReactionTooltipProps = {
  id?: number;
  reaction?: ReactionType;
  children: ReactNode;
  isComment?: boolean;
  getReactionUsers?: GenericGetReactionUsersFunction;
  users?: string[];
  popperProps?: Partial<PopperProps>;
};

type RenderReactionTooltipProps = {
  userNames: string[];
  reaction?: ReactionType;
  t: Function;
  maxHeight: boolean;
};

type GetTitleProps = {
  reaction?: ReactionType;
  t: Function;
  getReactionUsers?: GenericGetReactionUsersFunction;
  maxHeight: boolean;
};

const renderReactionTooltip = (props: RenderReactionTooltipProps) => {
  const { userNames, reaction, t, maxHeight } = props;

  if (userNames.length === 0) {
    return null;
  }

  const listToShow = getReactionList(userNames, maxHeight);
  const usersText = t('reactions.reaction_user', { count: userNames.length });
  const countText = t('reactions.reaction_count', {
    count: userNames.length - listToShow.length,
  });

  return (
    <Stack>
      <Typography
        variant="globalXXS"
        fontWeight="fontWeightSemiBold"
        sx={{
          display: 'flex',
          alignItems: 'center',
          gap: '2px',
          color: theme => theme.palette.newBase?.white,
        }}
      >
        {usersText}
        {reaction?.unified && (
          <Emoji
            unified={reaction.unified}
            size={12}
          />
        )}
        {!reaction?.unified && reaction?.emoji}
      </Typography>
      <Typography
        component="p"
        sx={{ fontSize: 'inherit' }}
      >
        {listToShow.map((userName, index) => (
          <Typography
            key={userName}
            component="span"
            sx={{
              display: 'block',
              fontSize: 'inherit',
              lineHeight: 1.3,
              textTransform: 'capitalize',
              color: theme => theme.palette.newBase?.white,
            }}
          >
            {index !== listToShow.length - 1 ? `${userName},` : userName}
          </Typography>
        ))}
      </Typography>
      {listToShow.length < userNames.length && (
        <Typography
          variant="globalXXS"
          sx={{ color: theme => theme.palette.newBase?.white }}
        >
          {countText}
        </Typography>
      )}
    </Stack>
  );
};

const getTitle = async (props: GetTitleProps) => {
  const { reaction, t, getReactionUsers, maxHeight } = props;

  try {
    if (!getReactionUsers || !reaction) {
      return '';
    }

    const response = await getReactionUsers(reaction.emoji);
    const users =
      'users' in response.data ? response.data.users : response.data.items;

    const userNames = users.reduce((usersAcc, user) => {
      const fullName = getFullName(user);
      if (fullName) {
        return [...usersAcc, fullName];
      }
      return usersAcc;
    }, [] as string[]);

    return renderReactionTooltip({ userNames, reaction, t, maxHeight });
  } catch (err) {
    const countText = t('reactions.reaction_count', { count: 0, users: '0' });
    return (
      <Stack>
        {countText}
        {reaction?.unified && (
          <Emoji
            unified={reaction.unified}
            size={12}
          />
        )}
        {!reaction?.unified && reaction?.emoji}
      </Stack>
    );
  }
};

const ReactionTooltip = ({
  id,
  reaction,
  children,
  getReactionUsers,
  users,
  popperProps,
  ...restProps
}: ReactionTooltipProps) => {
  const { t } = useLokaliseTranslation('web_only');
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const maxHeight = useMediaQuery('(max-height:500px)');
  const { data: title = '...' } = useQuery(
    reactionKeys.user.list(id ?? 0, reaction?.emoji ?? ''),
    () =>
      getTitle({
        reaction,
        t,
        getReactionUsers,
        maxHeight,
      }),
    {
      enabled: isOpen && !users && !!id && !!reaction,
    },
  );

  const open = () => setIsOpen(true);
  const close = () => setIsOpen(false);

  if (reaction?.count && reaction.count <= 0) {
    return <Stack>{children}</Stack>;
  }

  const titleToShow = users
    ? renderReactionTooltip({
        userNames: users,
        reaction,
        t,
        maxHeight,
      })
    : title;

  return (
    <Tooltip
      title={titleToShow}
      arrow
      onOpen={open}
      onClose={close}
      PopperProps={{
        popperOptions: {
          modifiers: [
            {
              name: 'preventOverflow',
              options: { altAxis: true, padding: 8 },
            },
          ],
        },
        sx: {
          '& .MuiTooltip-tooltip': {
            backgroundColor: theme =>
              theme.palette.new.background.elements.inverted,
          },
          '.MuiTooltip-arrow': {
            color: theme => theme.palette.new.background.elements.inverted,
          },
        },
        ...popperProps,
      }}
      {...restProps}
    >
      <Stack>{children}</Stack>
    </Tooltip>
  );
};

export default ReactionTooltip;
