import { FC } from 'react';
import { useMutation } from 'react-query';
import { useParams } from 'react-router';

import { AxiosError } from 'axios';
import { useModal } from '@material-hu/hooks/useModal';
import {
  IconChevronDown,
  IconCircleCheck,
  IconCircleX,
  IconHelp,
} from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';

import HuMenuList from '@material-hu/components/composed-components/MenuList';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuDialog from '@material-hu/components/design-system/Dialog';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import { useAuth } from 'src/contexts/JWTContext';
import { answerInvitation } from 'src/services/events';
import { EventName } from 'src/types/amplitude';
import { Event, InvitationStatus, ResponseFrom } from 'src/types/events';
import { ResponseError } from 'src/types/services';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { useInvalidateEvent } from '../hooks/useInvalidateEvent';

type Props = {
  invitationStatus: InvitationStatus;
  creatorId: number;
  event: Event;
  isCoOrganizer?: boolean;
};

enum EventResponseErrors {
  EVENT_FULL = 'EVENT_FULL',
}

const { ACCEPTED, DECLINED, MAY_ASSIST, PENDING } = InvitationStatus;

const buttonPropsMap = {
  null: {
    Icon: () => null,
    variant: 'primary',
    text: 'ANSWER',
  },
  [PENDING]: {
    Icon: () => null,
    variant: 'primary',
    text: 'ANSWER',
  },
  [ACCEPTED]: {
    Icon: IconCircleCheck,
    variant: 'secondary',
    text: 'INVITATION_STATUS.I_WILL_ATTEND',
  },
  [DECLINED]: {
    Icon: IconCircleX,
    variant: 'secondary',
    text: 'INVITATION_STATUS.I_WILL_NOT_ATTEND',
  },
  [MAY_ASSIST]: {
    Icon: IconHelp,
    variant: 'secondary',
    text: 'INVITATION_STATUS.I_MAY_ATTEND',
  },
} as const;

const responseOptions = [
  InvitationStatus.ACCEPTED,
  InvitationStatus.DECLINED,
  InvitationStatus.MAY_ASSIST,
];

export const ResponseButton: FC<Props> = props => {
  const { invitationStatus, creatorId, event, isCoOrganizer } = props;
  const eventId = event?.id;
  const { enqueueSnackbar } = useHuSnackbar();
  const invalidateEvent = useInvalidateEvent(eventId);
  const { user } = useAuth();
  const buttonProps = buttonPropsMap[invitationStatus];
  const { t } = useLokaliseTranslation('events');
  const { id } = useParams();
  const isEventDetailView = !!id;

  const { mutate, isLoading } = useMutation(
    (status: InvitationStatus) => answerInvitation(eventId, status),
    {
      onSuccess: (_, status) => {
        invalidateEvent();
        enqueueSnackbar({
          title: t('RESPONSE_RECORDED'),
          description: t('RESPONSE_RECORDED_MESSAGE', {
            status: t(status),
            name: event?.name,
          }),
          variant: 'info',
        });
        logEvent(EventName.EVENT_ASSISTANCE_RESPONDED, {
          status,
          source: isEventDetailView
            ? ResponseFrom.EVENT_DETAIL
            : ResponseFrom.INVITES_TAB,
        });
      },
      onError: (error: AxiosError<ResponseError>) => {
        handleSpotsError(error);
      },
    },
  );

  const handleSpotsError = (error: AxiosError<ResponseError>) => {
    if (error.response?.data.code === EventResponseErrors.EVENT_FULL) {
      showModal();
    } else {
      return enqueueSnackbar({
        title: t('RESPONSE_RECORDED_ERROR'),
        variant: 'error',
      });
    }
  };

  const onClose = () => {
    invalidateEvent();
    closeModal();
  };

  const { modal, showModal, closeModal } = useModal(() => (
    <HuDialog
      title={t('NO_REMAINING_SPOTS')}
      textBody={t('NO_REMAINING_SPOTS_MESSAGE')}
      primaryButtonProps={{
        children: t('REQUESTS:AGREE'),
        onClick: onClose,
      }}
      onClose={onClose}
    />
  ));

  const filteredResponseOptions = responseOptions.filter(
    option => option !== invitationStatus,
  );

  const isEventCreator = creatorId === user!.id;
  const disableButton = isEventCreator || isCoOrganizer;
  const disableToRespond = event?.remainingSpace === 0;

  const handlePropagation = (e: React.MouseEvent<HTMLDivElement>) => {
    e.stopPropagation();
  };

  return (
    <Box onClick={handlePropagation}>
      {modal}
      <HuMenuList
        options={filteredResponseOptions.map(o => ({
          onClick: () => mutate(o as InvitationStatus),
          Icon: buttonPropsMap[o].Icon,
          title: t(buttonPropsMap[o].text),
          disabled: o === InvitationStatus.ACCEPTED && disableToRespond,
        }))}
        customButton={
          <Button
            startIcon={<buttonProps.Icon />}
            variant={buttonProps.variant}
            endIcon={<IconChevronDown />}
            loading={isLoading}
            disabled={disableButton}
          >
            {t(buttonProps.text)}
          </Button>
        }
        disableMenu={disableButton}
      />
    </Box>
  );
};

export default ResponseButton;
