import React, {useCallback, useEffect, useState} from 'react';
import {ScrollView, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {FormProvider} from 'react-hook-form';
import {useMutation, useQueryClient} from 'react-query';
import {useDispatch} from 'react-redux';
import {
  Typography,
  Button,
  CloseButton,
  Dialog,
  HuGoFile,
  ProgressBar,
} from '@components';
import {useBackHandler} from '@hooks/useBackHandler';
import {useGoBack} from '@hooks/useGoBack';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {Navigation} from '@interfaces/navigation';
import {EVENTS_QUERY_KEYS} from '@modules/events/constants';
import {
  createEvent,
  editEvent,
  inviteUsersToEvent,
} from '@modules/events/services';
import {getAmplitudeParamEventType} from '@modules/events/utils';
import {EventsAmplitudeSource} from '@modules/events/interfaces';
import {showSnackbar} from '@redux/events';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {logAmplitudeEvent} from '@shared/utils';

import FirstStep from './components/FirstStep';
import SecondStep from './components/SecondStep';
import ThirdStep from './components/ThirdStep';
import {CreateEventFormField} from './interfaces';
import {styles} from './styles';
import {useCreateEventForm} from './useCreateEventForm';
import {getCoverPictureFromEvent, getEventFromValues} from './utils';

const TOTAL_STEPS = 3;

function EventCreation({
  navigation,
  route: {params},
}: Navigation<Screens.EVENT_CREATION>) {
  const eventToEdit = params?.event;
  const dispatch = useDispatch();
  const {t} = useTranslation();
  const {goBack} = useGoBack();
  const {theme} = useTheme();
  const queryClient = useQueryClient();
  const [currentStep, setCurrentStep] = useState(1);
  const [coverPickerFiles, setCoverPickerFiles] = useState<HuGoFile[]>(
    getCoverPictureFromEvent(eventToEdit),
  );
  const [newEventId, setNewEventId] = useState(0);
  const [showPreventModal, setShowPreventModal] = useState(false);
  const marginBottom = useSafeAreaBottomPadding();
  const {mutate: onInviteUsers, isLoading: isLoadingInvite} = useMutation(
    inviteUsersToEvent,
    {
      onSettled: (_data, _error, variables) => {
        setNewEventId(variables.eventId);
      },
    },
  );
  const {mutate: onCreateEvent, isLoading: isCreateLoading} = useMutation(
    createEvent,
    {
      onSuccess: (data, variables) => {
        if (variables.inviteAll) {
          onInviteUsers({eventId: data.id, selectAllUsers: true});
        } else {
          setNewEventId(data.id);
        }
        logAmplitudeEvent(AMPLITUDE_EVENTS.EVENT_CREATED, {
          eventId: data.id,
          eventType: getAmplitudeParamEventType(data),
        });
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.upcomingEvents);
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.organizedByMeEvents);
      },
    },
  );
  const {mutate: onEditEvent, isLoading: isEditLoading} = useMutation(
    editEvent,
    {
      onSuccess: data => {
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.upcomingEvents);
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.invitationEvents);
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.organizedByMeEvents);
        queryClient.invalidateQueries(EVENTS_QUERY_KEYS.event(data.id));
        goBack();
        dispatch(showSnackbar({title: t('events.edit_event_success')}));
      },
    },
  );
  const methods = useCreateEventForm(currentStep, eventToEdit);
  const {
    clearErrors,
    getValues,
    formState: {errors, isDirty},
    handleSubmit,
  } = methods;
  const isLoading = isCreateLoading || isEditLoading || isLoadingInvite;

  const onDialogClose = useCallback(() => setShowPreventModal(false), []);

  const onSuccessExit = useCallback(() => {
    setNewEventId(0);
    navigation.replace(Screens.EVENT_DETAIL, {
      eventId: newEventId,
      source: EventsAmplitudeSource.EVENT_CREATION,
    });
  }, [navigation, newEventId]);

  const onConfirmExit = useCallback(() => {
    onDialogClose();
    goBack();
  }, [goBack, onDialogClose]);

  const onCloseCreation = useCallback(() => {
    if (!isLoading) {
      isDirty ? setShowPreventModal(true) : goBack();
    }
    return true;
  }, [isDirty, isLoading, goBack]);

  useBackHandler(onCloseCreation);

  useEffect(() => {
    const headerRight = () => (
      <CloseButton disabled={isLoading} onPress={onCloseCreation} />
    );
    navigation.setOptions({headerRight});
  }, [isLoading, navigation, onCloseCreation, theme.text.neutral.default]);

  const onContinue = useCallback(() => {
    if (currentStep === TOTAL_STEPS) {
      const formValues = getValues();
      const baseEventObject = getEventFromValues(formValues);

      eventToEdit
        ? onEditEvent({...baseEventObject, id: eventToEdit.id})
        : onCreateEvent(baseEventObject);
    } else {
      setCurrentStep(currentStep + 1);
    }
  }, [currentStep, eventToEdit, getValues, onCreateEvent, onEditEvent]);

  const onGoBack = useCallback(() => {
    setCurrentStep(prev => {
      if (prev === 2) {
        [
          CreateEventFormField.Origin,
          CreateEventFormField.VideoCallUrl,
          CreateEventFormField.Location,
          CreateEventFormField.MaxGuests,
        ].forEach(clearErrors);
      } else if (prev === 3) {
        [CreateEventFormField.Privacy, CreateEventFormField.GroupId].forEach(
          clearErrors,
        );
      }
      return prev - 1;
    });
  }, [clearErrors]);

  return (
    <>
      <View
        style={[
          styles.screen,
          {backgroundColor: theme.background.elements.grey},
        ]}>
        <View
          style={[
            styles.progressContainer,
            {backgroundColor: theme.background.layout.tertiary},
          ]}>
          <ProgressBar
            description={t('events.create_event_form.description', {
              currentStep,
            })}
            title={t('events.create_event_form.title')}
            progress={currentStep}
            total={TOTAL_STEPS}
          />
        </View>
        <ScrollView
          bounces={false}
          showsVerticalScrollIndicator={false}
          style={{backgroundColor: theme.background.elements.grey}}
          contentContainerStyle={[
            styles.scrollViewContainer,
            {paddingBottom: marginBottom},
          ]}>
          <View style={styles.formContainer}>
            <FormProvider {...methods}>
              {currentStep === 1 ? (
                <FirstStep
                  coverPickerFiles={coverPickerFiles}
                  onSetCoverPickerFiles={setCoverPickerFiles}
                />
              ) : currentStep === 2 ? (
                <SecondStep />
              ) : (
                <ThirdStep isEditing={!!eventToEdit} />
              )}
            </FormProvider>
          </View>
          <View style={styles.buttonsContainer}>
            <Button
              disabled={
                !!Object.keys(errors).length || (currentStep === 3 && !isDirty)
              }
              isLoading={isLoading}
              text={t(
                currentStep === TOTAL_STEPS
                  ? eventToEdit
                    ? 'events.finish_editing'
                    : 'events.create_event'
                  : 'general.continue',
              )}
              onPress={handleSubmit(onContinue)}
            />
            {currentStep !== 1 && (
              <Button
                disabled={isLoading}
                text={t('general.back')}
                variant="tertiary"
                onPress={onGoBack}
              />
            )}
          </View>
        </ScrollView>
      </View>
      <Dialog
        isVisible={showPreventModal}
        title={t(
          `events.create_event_form.${
            eventToEdit ? 'prevent_edit_modal_title' : 'prevent_modal_title'
          }`,
        )}
        onClose={onDialogClose}
        footer={{
          primaryButton: {
            text: t('general.exit'),
            onPress: onConfirmExit,
          },
          secondaryButton: {
            text: t('general.cancel'),
            onPress: onDialogClose,
          },
        }}>
        <Typography>{t('events.changes_will_be_lost')}</Typography>
      </Dialog>
      <Dialog
        locked
        isVisible={!!newEventId}
        title={t('events.create_event_form.success_modal_title')}
        withCloseButton={false}
        footer={{
          primaryButton: {
            text: t('events.create_event_form.success_modal_button'),
            onPress: onSuccessExit,
          },
        }}>
        <Typography>
          {t('events.create_event_form.success_modal_text')}
        </Typography>
      </Dialog>
    </>
  );
}

export default EventCreation;
