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

import { type 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 { type GetViewersFunction } from 'src/hooks/usePostViewers';
import { type PostViewer } from 'src/types/posts';
import { useLokaliseTranslation } from 'src/utils/i18n';

export type ViewerTooltipProps = {
  postId: number;
  viewerCount: number;
  children: ReactNode;
  getViewers?: GetViewersFunction;
  users?: PostViewer[];
  popperProps?: Partial<PopperProps>;
  onViewerCountUpdate?: (count: number) => void;
};

type RenderViewerTooltipProps = {
  userNames: string[];
  t: (key: string, params?: Record<string, unknown>) => string;
  maxHeight: boolean;
};

type GetTitleProps = {
  t: (key: string, params?: Record<string, unknown>) => string;
  getViewers?: GetViewersFunction;
  maxHeight: boolean;
  onViewerCountUpdate?: (count: number) => void;
};

const MAX_TOOLTIP_USERS = 10;

const getViewerList = (userNames: string[], maxHeight: boolean): string[] => {
  const maxUsers = maxHeight ? 5 : MAX_TOOLTIP_USERS;
  return userNames.slice(0, maxUsers);
};

const renderViewerTooltip = (props: RenderViewerTooltipProps) => {
  const { userNames, t, maxHeight } = props;

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

  const listToShow = getViewerList(userNames, maxHeight);
  const remainingCount = userNames.length - listToShow.length;

  return (
    <Stack>
      <Typography
        variant="globalXXS"
        fontWeight="fontWeightSemiBold"
        sx={{
          display: 'flex',
          alignItems: 'center',
          gap: '2px',
          color: theme => theme.palette.newBase?.white,
          mb: 0.5,
        }}
      >
        {t('seen_by')}
      </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>
      {remainingCount > 0 && (
        <Typography
          variant="globalXXS"
          sx={{ color: theme => theme.palette.newBase?.white, mt: 0.5 }}
        >
          {t('see_more_viewers', { count: remainingCount })}
        </Typography>
      )}
    </Stack>
  );
};

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

  try {
    if (!getViewers) {
      return '';
    }

    const response = await getViewers({ limit: MAX_TOOLTIP_USERS });
    const viewers = response.data.items || [];

    if (!response.data.cursor && onViewerCountUpdate) {
      onViewerCountUpdate(viewers.length);
    }

    const userNames = viewers.reduce<string[]>((acc, item) => {
      const name = [item.viewer.firstName, item.viewer.lastName]
        .filter(Boolean)
        .join(' ');
      if (name) acc.push(name);
      return acc;
    }, []);

    return renderViewerTooltip({ userNames, t, maxHeight });
  } catch {
    return (
      <Stack>
        <Typography
          variant="globalXXS"
          sx={{ color: theme => theme.palette.newBase?.white }}
        >
          {t('loading_viewers')}
        </Typography>
      </Stack>
    );
  }
};

const ViewerTooltip = ({
  postId,
  viewerCount,
  children,
  getViewers,
  users,
  popperProps,
  onViewerCountUpdate,
  ...restProps
}: ViewerTooltipProps) => {
  const { t } = useLokaliseTranslation('post');
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const maxHeight = useMediaQuery('(max-height:500px)');
  const { data: title = t('loading_viewers') } = useQuery(
    ['post-viewers-tooltip', postId, maxHeight],
    () =>
      getTitle({
        t,
        getViewers,
        maxHeight,
        onViewerCountUpdate,
      }),
    {
      enabled: isOpen && !users && !!postId && !!getViewers && viewerCount > 0,
      staleTime: 10_000,
    },
  );

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

  if (viewerCount <= 0) {
    return <Stack>{children}</Stack>;
  }

  const titleToShow = users
    ? renderViewerTooltip({
        userNames: users
          .map(item =>
            [item.viewer.firstName, item.viewer.lastName]
              .filter(Boolean)
              .join(' '),
          )
          .filter(Boolean),
        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.text.neutral.default,
          },
          '.MuiTooltip-arrow': {
            color: theme => theme.palette.new.text.neutral.default,
          },
        },
        ...popperProps,
      }}
      {...restProps}
    >
      <Stack>{children}</Stack>
    </Tooltip>
  );
};

export default ViewerTooltip;
