import { FC } from 'react';

import { useInfiniteQuery } from 'react-query';

import Avatar from '@material-hu/mui/Avatar';
import ListItem from '@material-hu/mui/ListItem';
import ListItemAvatar from '@material-hu/mui/ListItemAvatar';
import ListItemText from '@material-hu/mui/ListItemText';
import Skeleton from '@material-hu/mui/Skeleton';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import Pills from '@material-hu/components/design-system/Pills';
import useGeneralError from 'src/hooks/useGeneralError';
import { getGroupPollVoters } from 'src/services/groups';
import { getPollVoters } from 'src/services/posts';
import { PollOption } from 'src/types/posts';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';

import InfiniteList from 'src/components/list/InfiniteList';
import { usePost } from 'src/components/post/PostContext';

import { feedKeys } from '../../queries';

type PollVotersDrawerProps = {
  postId: number;
  pollId: number;
  pollOption: PollOption;
  closeDrawer: () => void;
};

const VOTERS_LIMIT = 20;

const PollVotersDrawerContent: FC<PollVotersDrawerProps> = ({
  postId,
  pollId,
  pollOption,
}) => {
  const { t } = useTranslation('post');
  const showGeneralError = useGeneralError();
  const { groupId } = usePost();

  const isGroupPost = !!groupId;

  const {
    data,
    isLoading,
    error,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    feedKeys.poll.voters(postId, pollId, pollOption.id),
    ({ pageParam = '' }) => {
      if (isGroupPost) {
        return getGroupPollVoters(
          groupId,
          postId,
          pollId,
          pollOption.id,
          VOTERS_LIMIT,
          pageParam,
        );
      } else {
        return getPollVoters(
          postId,
          pollId,
          pollOption.id,
          VOTERS_LIMIT,
          pageParam,
        );
      }
    },
    {
      getNextPageParam: lastPage => lastPage?.data?.cursor,
      onError: err => {
        showGeneralError(err, t('error_loading_voters'));
      },
      staleTime: 2000,
    },
  );

  // Flatten all pages of voters
  const allFetchedVoters = data?.pages.flatMap(page => page.data.items) || [];

  // Use fetched data if available, otherwise use initial voters
  const displayVoters =
    allFetchedVoters.length > 0 ? allFetchedVoters : pollOption.voters;

  return (
    <Stack>
      <Typography
        variant="globalM"
        fontWeight="fontWeightSemiBold"
      >
        {t('option')}: {pollOption.option}
      </Typography>
      <Typography
        variant="globalXS"
        color={theme => theme.palette.new.text.neutral.lighter}
        sx={{ mb: 2 }}
      >
        {t('poll_voters_count', { count: pollOption.answerCount })}
      </Typography>

      {error ? (
        <Typography
          variant="globalXS"
          color="error"
          sx={{ mb: 2 }}
        >
          {t('error_loading_voters')}
        </Typography>
      ) : null}

      <InfiniteList
        isLoading={isLoading}
        isSuccess={!!data}
        isEmpty={allFetchedVoters.length === 0}
        fetchNextPage={fetchNextPage}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
        sx={{ overflow: 'auto' }}
        loadingSkeleton={isLoading || isFetchingNextPage}
        renderSkeleton={
          <Stack sx={{ gap: 2, mt: 1 }}>
            {[...Array(3)].map((_, idx) => (
              <Stack
                key={idx}
                direction="row"
                alignItems="center"
                gap={2}
              >
                <Skeleton
                  variant="circular"
                  animation="wave"
                  width={40}
                  height={40}
                />
                <Skeleton
                  variant="rectangular"
                  animation="wave"
                  sx={{ borderRadius: 1 }}
                  // "Random" width between 40% and 80%
                  width={`${40 + ((idx * 13) % 21)}%`}
                  height={40}
                />
              </Stack>
            ))}
          </Stack>
        }
      >
        {displayVoters?.map(voter => (
          <ListItem
            key={voter.id}
            sx={{ px: 0 }}
          >
            <ListItemAvatar>
              <Avatar
                src={voter.profilePicture}
                alt={`${voter.firstName} ${voter.lastName}`}
                sx={{ width: 40, height: 40 }}
              />
            </ListItemAvatar>
            <ListItemText
              primary={`${voter.firstName} ${voter.lastName}`}
              primaryTypographyProps={{
                variant: 'globalS',
                fontWeight: 'fontWeightSemiBold',
              }}
            />
            {voter.isExternal && (
              <Pills
                label={t('group:external')}
                type="neutral"
                size="small"
                hasIcon={false}
              />
            )}
          </ListItem>
        ))}
      </InfiniteList>
    </Stack>
  );
};

export const getPollVotersDrawerConfig = (
  props: PollVotersDrawerProps & { closeDrawer: () => void; open: boolean },
) => {
  const { t } = useTranslation('post');
  const { closeDrawer, ...drawerProps } = props;

  return {
    title: t('voters'),
    hasBackButton: true,
    children: (
      <PollVotersDrawerContent
        {...drawerProps}
        closeDrawer={closeDrawer}
      />
    ),
  };
};
