import { type FC, Fragment, useState } from 'react';
import { useInfiniteQuery, useMutation, useQueryClient } from 'react-query';
import { useNavigate, useParams } from 'react-router-dom';

import './i18n';

import PersonAddIcon from '@material-hu/icons/material/PersonAdd';
import Avatar from '@material-hu/mui/Avatar';
import Box from '@material-hu/mui/Box';
import ButtonBase from '@material-hu/mui/ButtonBase';
import Chip from '@material-hu/mui/Chip';
import Divider from '@material-hu/mui/Divider';
import List from '@material-hu/mui/List';
import ListItem from '@material-hu/mui/ListItem';
import ListItemAvatar from '@material-hu/mui/ListItemAvatar';
import ListItemText from '@material-hu/mui/ListItemText';
import Typography from '@material-hu/mui/Typography';

import { useAuth } from 'src/contexts/JWTContext';
import useGeneralError from 'src/hooks/useGeneralError';
import { profileRoutes } from 'src/pages/dashboard/profile/routes';
import {
  addUsersToGroupChat,
  getParticipantsOfGroup,
} from 'src/services/chats';
import { type User } from 'src/types/user';
import { getListItemsLength, getNextPage } from 'src/utils/pagination';

import { RegularChatAvatar } from 'src/components/dashboard/chat/ChatAvatar';
import { RegularChatName } from 'src/components/dashboard/chat/ChatName';
import { useTranslation } from 'src/components/dashboard/chat/ChatThreadInfo/i18n';
import { chatKeys } from 'src/components/dashboard/chat/queries';
import InfiniteList from 'src/components/list/InfiniteList';

import AddParticipantsDialog from './AddParticipantsDialog';
import ParticipantMenu from './ParticipantMenu';

type ChatThreadInfoParticipantsProps = {
  editable?: boolean;
  limit?: number;
};

const ChatThreadInfoParticipants: FC<
  ChatThreadInfoParticipantsProps
> = props => {
  const { limit = 10, editable = false } = props;

  const [addOpen, setAddOpen] = useState<boolean>(false);

  const { user } = useAuth();
  const { id } = useParams();
  const { t } = useTranslation();
  const showGeneralError = useGeneralError();
  const navigate = useNavigate();
  const queryClient = useQueryClient();

  const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useInfiniteQuery(
      chatKeys.participants(id),
      ({ pageParam = 1 }) => getParticipantsOfGroup(id, pageParam, limit),
      {
        getNextPageParam: (lastPage, pages) =>
          getNextPage(getListItemsLength(pages), limit, pages),
        onError: err => showGeneralError(err, t('ERROR_GET_PARTICIPANTS')),
      },
    );

  const { mutate: addUsers } = useMutation(
    (usersIds: number[]) => addUsersToGroupChat(id, usersIds),
    {
      onError: err => {
        showGeneralError(err, t('ERROR_ADD_PARTICIPANTS'));
      },
      onSuccess: () => {
        queryClient.invalidateQueries(chatKeys.participants(id));
        queryClient.invalidateQueries(chatKeys.detail(id));
      },
    },
  );

  const handleClick = (clickedId: number) => {
    navigate(profileRoutes.profile(clickedId));
  };

  const handleAddOpen = () => {
    setAddOpen(true);
  };

  const handleAddClose = () => {
    setAddOpen(false);
  };

  const handleAdd = (users: User[]) => {
    if (users.length > 0) {
      addUsers(users.map(userMap => userMap.id));
    }
  };

  const totalParticipants = data?.pages[0]?.data.count;

  return (
    <Box sx={{ mx: 3 }}>
      <AddParticipantsDialog
        open={addOpen}
        onAdd={handleAdd}
        onClose={handleAddClose}
      />
      <Typography
        variant="subtitle1"
        sx={{ my: 2 }}
      >
        {t('PARTICIPANTS', {
          count: totalParticipants,
        })}
      </Typography>
      <List>
        {editable && (
          <Box>
            <ListItem
              alignItems="flex-start"
              sx={{ p: 0 }}
            >
              <ButtonBase
                onClick={handleAddOpen}
                sx={{
                  flex: 1,
                  py: 1,
                }}
              >
                <ListItemAvatar>
                  <Avatar
                    sx={{
                      backgroundColor: theme => theme.palette.primary.main,
                    }}
                  >
                    <PersonAddIcon />
                  </Avatar>
                </ListItemAvatar>
                <ListItemText
                  primary={t('ADD_PARTICIPANTS')}
                  sx={{ textAlign: 'left' }}
                />
              </ButtonBase>
            </ListItem>
            <Divider
              variant="inset"
              component="li"
              sx={{ marginLeft: '56px' }}
            />
          </Box>
        )}
        <InfiniteList
          isSuccess={!!data}
          isLoading={isLoading}
          fetchNextPage={fetchNextPage}
          hasNextPage={hasNextPage}
          isFetchingNextPage={isFetchingNextPage}
          sx={{
            mt: 2,
            position: 'relative',
            zIndex: 0,
          }}
        >
          {data?.pages?.map((participantPage, i) => (
            <Fragment key={i}>
              {participantPage?.data?.items?.map((participant, index) => (
                <Box key={participant.id}>
                  <ListItem
                    alignItems="center"
                    sx={{ p: 0 }}
                  >
                    <ButtonBase
                      onClick={() => handleClick(participant.id)}
                      sx={{
                        flex: 1,
                        py: 1,
                        pr: 1,
                      }}
                    >
                      <ListItemAvatar>
                        <RegularChatAvatar
                          otherUser={participant}
                          color={participant.color}
                          withLink={false}
                        />
                      </ListItemAvatar>
                      <ListItemText
                        primary={
                          <Box
                            sx={{
                              width: participant.isAdmin ? '180px' : '200px',
                              overflow: 'hidden',
                              textOverflow: 'ellipsis',
                            }}
                          >
                            <RegularChatName
                              otherUser={participant}
                              withLink={false}
                            />
                          </Box>
                        }
                        sx={{
                          textAlign: 'left',
                        }}
                      />
                      {participant.isAdmin && (
                        <Chip
                          label={t('ADMIN')}
                          variant="outlined"
                          color="primary"
                          size="small"
                        />
                      )}
                    </ButtonBase>
                    <Box
                      sx={{
                        width: 30,
                      }}
                    >
                      {editable && participant.id !== user.id && (
                        <ParticipantMenu participant={participant} />
                      )}
                    </Box>
                  </ListItem>
                  {index < totalParticipants - 1 && (
                    <Divider
                      variant="inset"
                      component="li"
                      sx={{ marginLeft: '56px' }}
                    />
                  )}
                </Box>
              ))}
            </Fragment>
          ))}
        </InfiniteList>
      </List>
    </Box>
  );
};

export default ChatThreadInfoParticipants;
