import { FC, useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';
import { useNavigate } from 'react-router';

import { useModal } from '@material-hu/hooks/useModal';
import Container from '@material-hu/mui/Container';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuDialog from '@material-hu/components/design-system/Dialog';
import HuProgressBar from '@material-hu/components/design-system/ProgressIndicators/ProgressBar';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { addEventOrganizer, createEvent, editEvent } from 'src/services/events';
import { EventName } from 'src/types/amplitude';
import { Event, EventType } from 'src/types/events';
import { FeatureFlags } from 'src/types/featureFlags';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { FocusNavbar } from '../components/FocusNavbar';
import { useEventGroups } from '../hooks/useEventGroups';
import { eventsRoutes } from '../routes';
import { getInitialFormValues, preprocessFormData } from '../utils';

import DetailsStep from './components/DetailsStep';
import LocationStep from './components/LocationStep';
import OrganizersStep from './components/OrganizersStep';
import VisibilityStep from './components/VisibilityStep';

type Props = {
  event?: Event;
};

enum Steps {
  DETAILS,
  LOCATION,
  VISIBILITY,
  ORGANIZERS_CONFIG,
}

export const NewEvent: FC<Props> = ({ event }) => {
  const [step, setStep] = useState<Steps>(Steps.DETAILS);

  const initialFormValues = useMemo(() => getInitialFormValues(event), [event]);
  const isMultipleOrganizersEnabled = useFeatureFlag(
    FeatureFlags.EVENTS_MULTIPLE_ORGANIZERS_ENABLED,
  );

  const form = useForm({
    defaultValues: initialFormValues,
    mode: 'onChange',
  });

  const {
    handleSubmit,
    formState: { isSubmitting },
    watch,
    trigger,
  } = form;

  const { inviteAll, locationType, visibility } = watch();

  const eventId = event?.id;
  const { t } = useLokaliseTranslation('events');
  const navigate = useNavigate();
  const { enqueueSnackbar } = useHuSnackbar();
  const ThemeProvider = useHuGoTheme();

  const { invitationMutation } = useEventGroups({});

  const addOrganizerMutation = useMutation(
    (variables: { eventId: number; userIds: number[] }) =>
      addEventOrganizer(variables.eventId, variables.userIds),
  );

  const { modal, showModal, closeModal } = useModal(
    ({ id }: { id: number }) => (
      <HuDialog
        onClose={() => {
          closeModal();
          navigate(eventsRoutes.events());
        }}
        title={t('CREATE_EVENT_FORM.SUCCESS_MODAL_TITLE')}
        textBody={t('CREATE_EVENT_FORM.SUCCESS_MODAL_TEXT')}
        primaryButtonProps={{
          children: t('CREATE_EVENT_FORM.SUCCESS_MODAL_BUTTON'),
          onClick: () => navigate(eventsRoutes.event(id)),
        }}
      />
    ),
    {
      onClose: () => {
        closeModal();
        navigate(eventsRoutes.events());
      },
    },
  );

  const {
    mutate,
    isError,
    isLoading: isLoadingMutation,
  } = useMutation(eventId ? editEvent : createEvent, {
    onSuccess: r => {
      if (eventId) {
        enqueueSnackbar({ title: t('EDIT_EVENT_SUCCESS'), variant: 'info' });
        navigate(eventsRoutes.event(eventId));
      } else {
        showModal({ id: r.data.id });

        if (inviteAll) {
          const invitationsData = {
            selectAllUsers: true,
            id: r.data.id,
          };
          invitationMutation(invitationsData);
        }

        const coOrganizers = form.getValues('coOrganizers');
        if (coOrganizers?.length > 0) {
          addOrganizerMutation.mutate({
            eventId: r.data.id,
            userIds: coOrganizers,
          });
        }

        logEvent(EventName.EVENT_CREATED, {
          eventId: r.data.id,
          eventType:
            r.data.location && r.data.videoCallUrl
              ? EventType.IN_PERSON_AND_ONLINE
              : EventType.IN_PERSON,
        });
      }
    },
  });

  useEffect(() => {
    if (!eventId) {
      logEvent(EventName.EVENT_CREATION_STARTED);
    }
  }, []);

  const onSubmit = handleSubmit(async values => {
    const processedValues = await preprocessFormData(values, eventId);
    mutate(processedValues);
  });

  const steps = [
    { Component: DetailsStep, title: t('CREATE_EVENT_FORM.TITLE') },
    { Component: LocationStep, title: t('LOCATION_FOR_ATTENDEES') },
    {
      Component: VisibilityStep,
      title: t('EVENT_CONFIGURATION'),
      props: { hasError: isError, event },
    },
    ...(isMultipleOrganizersEnabled
      ? [
          {
            Component: OrganizersStep,
            title: t('SELECT_ORGANIZERS_TITLE'),
            props: { event },
          },
        ]
      : []),
  ];

  const currentStep = steps[step];
  const isLastStep = step === steps.length - 1;

  const lastStepLabel = eventId ? 'FINISH_EDITING' : 'CREATE_EVENT';

  const disabledOptions: Record<Steps, boolean> = {
    [Steps.DETAILS]: false,
    [Steps.LOCATION]: !(
      locationType.presencial ||
      locationType.videocall ||
      locationType.liveStream
    ),
    [Steps.VISIBILITY]: !(visibility.allCommunity || visibility.group),
    [Steps.ORGANIZERS_CONFIG]: false,
  };

  return (
    <ThemeProvider>
      <FormProvider {...form}>
        <FocusNavbar eventId={eventId}>
          {modal}
          <Container
            maxWidth="md"
            sx={{ minHeight: 'calc(100vh - 160px)' }}
          >
            <Stack
              sx={{
                py: 4,
                px: 3,
              }}
            >
              <HuProgressBar
                total={steps.length}
                current={step + 1}
                variant="determinate"
                title={currentStep.title}
                description={t('STEP_DESCRIPTION', {
                  step: step + 1,
                  totalSteps: steps.length,
                })}
              />
              <Divider sx={{ mt: 2, mb: 4 }} />
              <currentStep.Component {...currentStep.props} />
            </Stack>
          </Container>
          <Stack
            sx={{
              backgroundColor: theme =>
                theme.palette.new.background.elements.grey,
              p: 2,
            }}
          >
            <Container
              maxWidth="md"
              sx={{
                display: 'flex',
                alignItems: 'center',
                px: '45px !important',
                justifyContent:
                  step > Steps.DETAILS ? 'space-between' : 'flex-end',
              }}
            >
              {step > Steps.DETAILS && (
                <Button
                  variant="secondary"
                  size="large"
                  onClick={() => setStep(step - 1)}
                  sx={{ mr: 'auto' }}
                >
                  {t('GO_BACK')}
                </Button>
              )}
              <Button
                loading={isSubmitting || isLoadingMutation}
                variant="primary"
                size="large"
                disabled={disabledOptions[step]}
                onClick={
                  isLastStep
                    ? onSubmit
                    : () => {
                        trigger().then(r => r && setStep(step + 1));
                      }
                }
              >
                {t(isLastStep ? lastStepLabel : 'CONTINUE')}
              </Button>
            </Container>
          </Stack>
        </FocusNavbar>
      </FormProvider>
    </ThemeProvider>
  );
};

export default NewEvent;
