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

import KeyboardArrowDownIcon from '@material-hu/icons/material/KeyboardArrowDown';
import Box from '@material-hu/mui/Box';
import Chip from '@material-hu/mui/Chip';
import { grey } from '@material-hu/mui/colors';
import Fade from '@material-hu/mui/Fade';
import Menu from '@material-hu/mui/Menu';
import MenuItem from '@material-hu/mui/MenuItem';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';

import useGeneralError from 'src/hooks/useGeneralError';
import { assignForm, changeStatusForm } from 'src/services/forms';
import { ChatListItem } from 'src/types/chats';
import { FormPossibleStatus } from 'src/types/forms';

import ChatSLA from 'src/components/dashboard/chat/ChatThread/ChatSLA';
import { useTranslation } from 'src/components/dashboard/chat/i18n';
import {
  formKeys,
  updateListsForms,
} from 'src/components/dashboard/form/queries';

export type ChatThreadStatusProps = {
  thread: ChatListItem;
};

const ChatThreadStatus: FC<ChatThreadStatusProps> = props => {
  const { thread } = props;

  const { id } = useParams();
  const { t } = useTranslation();
  const queryClient = useQueryClient();
  const showGeneralError = useGeneralError();

  const [openStatusChange, setOpenStatusChange] = useState<null | HTMLElement>(
    null,
  );
  const open = Boolean(openStatusChange);

  const handleOpen = (event: React.MouseEvent<HTMLElement>) =>
    setOpenStatusChange(event.currentTarget);

  const handleClose = () => setOpenStatusChange(null);

  const invalidateQueriesMutation = useMutation(async () => {
    await queryClient.invalidateQueries(formKeys.detail(id));
    await queryClient.invalidateQueries(formKeys.messages.list(id));
    await updateListsForms();
  });

  const mutation = useMutation((newStatus: string) =>
    changeStatusForm(thread.id, { status: newStatus }),
  );

  const handleStatusChange = (newStatus: string) => {
    if (mutation.isLoading || invalidateQueriesMutation.isLoading) {
      return;
    }
    mutation.mutate(newStatus, {
      onSuccess: async () => {
        handleClose();
        await invalidateQueriesMutation.mutateAsync();
      },
      onError: error => {
        showGeneralError(error, t('ERROR_CHANGE_STATUS'));
      },
    });
  };

  const handleAssign = () => {
    const formId = thread.id;
    assignMutation.mutate(Number(formId));
  };

  const assignMutation = useMutation(assignForm, {
    onSuccess: async () => {
      await invalidateQueriesMutation.mutateAsync();
    },
    onError: error => {
      showGeneralError(error, t('ERROR_ASSIGNING_FORM'));
    },
  });

  const hasOptions = thread.possibleStatusDestinations.length > 0;

  return (
    <Box
      id="chat-toolbar"
      className="toolbar"
    >
      <Stack
        sx={{
          flexDirection: 'row',
          justifyContent: 'space-between',
          width: '100%',
        }}
      >
        <Stack sx={{ flexDirection: 'row', gap: 4, width: '100%' }}>
          {(thread.status === FormPossibleStatus.UNASSIGNED ||
            thread.status === FormPossibleStatus.ASSIGNED) && (
            <ChatSLA
              sla={thread.timeToFirstResponseSlaTimer}
              status={thread.status}
            />
          )}
          <ChatSLA
            sla={thread.timeToResolutionSlaTimer}
            status={thread.status}
          />
        </Stack>
        <Stack
          sx={{
            width: '100%',
            flexDirection: 'row',
            justifyContent: 'flex-end',
            gap: 1,
          }}
        >
          {thread.status === FormPossibleStatus.UNASSIGNED && (
            <Button
              variant="outlined"
              color="primary"
              onClick={handleAssign}
              size="small"
              sx={{
                width: 'fit-content',
                minWidth: 'fit-content',
                flex: '0 !important',
              }}
            >
              {t('ASSIGN_ME_FORM')}
            </Button>
          )}
          <Button
            variant="contained"
            disableElevation
            onClick={hasOptions ? handleOpen : undefined}
            sx={{
              flex: '0 !important',
              borderRadius: '4px',
              width: 'fit-content',
              minWidth: 'fit-content',
              cursor: hasOptions ? 'pointer' : 'default',
            }}
            endIcon={hasOptions && <KeyboardArrowDownIcon />}
          >
            {t(thread.status)}
          </Button>
          <Menu
            id="fade-menu"
            MenuListProps={{
              'aria-labelledby': 'fade-button',
            }}
            anchorEl={openStatusChange}
            open={open}
            onClose={handleClose}
            TransitionComponent={Fade}
          >
            {thread.possibleStatusDestinations.map(option => (
              <MenuItem
                onClick={() => handleStatusChange(option)}
                key={option}
              >
                <Stack
                  sx={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}
                >
                  <Typography sx={{ fontWeight: 600 }}>
                    {t('MOVE_TO')}
                  </Typography>
                  <Chip
                    label={t(option)}
                    color="secondary"
                    size="small"
                    sx={{ backgroundColor: grey[500] }}
                  />
                </Stack>
              </MenuItem>
            ))}
          </Menu>
        </Stack>
      </Stack>
    </Box>
  );
};

export default ChatThreadStatus;
