import {useCallback, useState} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useNavigation} from '@react-navigation/native';
import {useMutation, useQueryClient} from '@tanstack/react-query';
import {
  IconCheck,
  IconEdit,
  IconTrash,
  IconX,
} from '@tabler/icons-react-native';
import {Button} from '@components';
import {useGoBack} from '@hooks/useGoBack';
import {useModalHandler} from '@hooks/useModalHandler';
import {useBackHandler} from '@hooks/useBackHandler';
import {User} from '@interfaces/user';
import {
  changeTimeOffRequestState,
  changeTimeOffStepState,
} from '@modules/timeOff/services';
import {
  CalendarRowsFilters,
  TimeOffRequestState,
  TimeOffStepState,
} from '@modules/timeOff/interfaces';
import {TIME_OFF_QUERY_KEYS} from '@modules/timeOff/constants';
import {showSnackbar} from '@redux/dispatchers';
import {fetchModulesNotifications, logAmplitudeEvent} from '@shared/utils';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {ModulesNotifications} from '@shared/notifications';

import ResolutionReason, {
  type ResolutionReasonMode,
} from './components/ResolutionReason';
import {Source} from './constants';
import {styles} from './styles';

interface Props {
  requestId: number;
  stepId?: number;
  policyTypeId: number;
  approvalStepsCount: number;
  showCancelButton?: boolean;
  canEditRequest?: boolean;
  editIssuer?: User;
  isIssuer: boolean;
  calendarRowsFilters?: CalendarRowsFilters;
}

function ActionButtons({
  requestId,
  stepId,
  policyTypeId,
  approvalStepsCount,
  showCancelButton,
  canEditRequest,
  editIssuer,
  isIssuer,
  calendarRowsFilters,
}: Props) {
  const {t} = useTranslation();
  const navigation = useNavigation();
  const queryClient = useQueryClient();
  const {
    isVisible: isResolutionDialogVisible,
    onCloseModal: onCloseResolutionDialog,
    onOpenModal: onOpenResolutionDialog,
  } = useModalHandler();
  const [answerLoading, setAnswerLoading] =
    useState<Nullable<TimeOffStepState | TimeOffRequestState>>(null);
  const [pendingAction, setPendingAction] =
    useState<Nullable<ResolutionReasonMode>>(null);
  const {goBack} = useGoBack();

  useBackHandler(goBack);

  const invalidateQueries = (isCancellingRequest = true) => {
    isCancellingRequest &&
      !calendarRowsFilters &&
      queryClient.invalidateQueries({
        queryKey: TIME_OFF_QUERY_KEYS.collaboratorRequests,
      });

    queryClient.invalidateQueries({
      queryKey: TIME_OFF_QUERY_KEYS.managementRequests,
    });

    !!calendarRowsFilters &&
      queryClient.invalidateQueries({
        queryKey: TIME_OFF_QUERY_KEYS.calendarRows(calendarRowsFilters),
      });

    (!isCancellingRequest || isIssuer) &&
      fetchModulesNotifications([ModulesNotifications.TIME_OFF]);
  };

  const changeStepStateMutation = useMutation({
    mutationFn: changeTimeOffStepState,
    onSuccess: (_, {state, resolutionReason, comment}) => {
      setAnswerLoading(null);
      invalidateQueries(false);
      logAmplitudeEvent(AMPLITUDE_EVENTS.TIME_OFF_APPROVAL_RESOLVED, {
        source: Source.MANAGEMENT_DETAIL,
        requestId,
        policyTypeId,
        state,
        resolutionReason: resolutionReason ?? comment,
      });
      goBack();
      showSnackbar({
        title: t(
          `time_off.${
            state === TimeOffStepState.APPROVED
              ? 'successfully_approved'
              : 'successfully_rejected'
          }`,
        ),
      });
    },
    onError: () => {
      setAnswerLoading(null);
      invalidateQueries(false);
      goBack();
    },
  });

  const changeRequestStateMutation = useMutation({
    mutationFn: changeTimeOffRequestState,
    onSuccess: (_, {state, resolutionReason}) => {
      setAnswerLoading(null);
      invalidateQueries();
      logAmplitudeEvent(AMPLITUDE_EVENTS.TIME_OFF_APPROVAL_RESOLVED, {
        source: isIssuer
          ? Source.COLLABORATOR_DETAIL
          : Source.MANAGEMENT_DETAIL,
        requestId,
        policyTypeId,
        state,
        resolutionReason,
      });
      goBack();
      state === TimeOffRequestState.CANCELLED &&
        showSnackbar({title: t('time_off.successfully_cancelled')});
    },
    onError: () => {
      setAnswerLoading(null);
      invalidateQueries();
      goBack();
    },
  });

  const onCancelRequest = useCallback(
    (modalText?: string) => {
      setAnswerLoading(TimeOffRequestState.CANCELLED);
      onCloseResolutionDialog();
      changeRequestStateMutation.mutate({
        id: requestId,
        state: TimeOffRequestState.CANCELLED,
        resolutionReason: modalText,
      });
    },
    [changeRequestStateMutation, onCloseResolutionDialog, requestId],
  );

  const onOpenModalForAction = useCallback(
    (action: ResolutionReasonMode) => () => {
      setPendingAction(action);
      onOpenResolutionDialog();
    },
    [onOpenResolutionDialog],
  );

  const onCloseResolutionModal = useCallback(() => {
    onCloseResolutionDialog();
  }, [onCloseResolutionDialog]);

  const onChangeStepState = useCallback(
    (state: TimeOffStepState) => (modalText?: string) => {
      setAnswerLoading(state);
      onCloseResolutionDialog();
      const isMultiStep = approvalStepsCount > 1;
      const comment = isMultiStep ? modalText : undefined;
      const resolutionReason = !isMultiStep ? modalText : undefined;
      changeStepStateMutation.mutate({
        id: requestId,
        stepId: stepId!,
        state,
        ...(!!comment && {comment}),
        resolutionReason,
      });
    },
    [
      changeStepStateMutation,
      onCloseResolutionDialog,
      requestId,
      stepId,
      approvalStepsCount,
    ],
  );

  const onEditRequest = useCallback(() => {
    navigation.navigate(Screens.MAKE_REQUEST, {
      policyTypeId,
      issuer: editIssuer,
      requestId,
    });
  }, [editIssuer, requestId, navigation, policyTypeId]);

  return (
    <>
      {canEditRequest && (
        <Button
          disabled={!!answerLoading}
          IconLeft={IconEdit}
          onPress={onEditRequest}
          text={t('general.edit')}
          variant="secondary"
        />
      )}
      {showCancelButton ? (
        <>
          <Button
            disabled={!!answerLoading}
            IconLeft={IconTrash}
            isLoading={answerLoading === TimeOffRequestState.CANCELLED}
            onPress={onOpenModalForAction('cancel')}
            text={t('general.cancel')}
            variant="secondary"
          />
          <ResolutionReason
            mode="cancel"
            isVisible={isResolutionDialogVisible}
            onAccept={onCancelRequest}
            onClose={onCloseResolutionModal}
          />
        </>
      ) : (
        <View style={styles.container}>
          <Button
            disabled={!!answerLoading}
            IconLeft={IconCheck}
            isLoading={answerLoading === TimeOffStepState.APPROVED}
            onPress={onOpenModalForAction('approve')}
            text={t('time_off.approve')}
            variant="primary"
          />
          <Button
            disabled={!!answerLoading}
            IconLeft={IconX}
            isLoading={answerLoading === TimeOffStepState.REJECTED}
            onPress={onOpenModalForAction('reject')}
            text={t('time_off.reject')}
            variant="secondary"
          />
          <ResolutionReason
            mode={pendingAction ?? 'reject'}
            isVisible={isResolutionDialogVisible}
            onAccept={
              pendingAction === 'approve'
                ? onChangeStepState(TimeOffStepState.APPROVED)
                : onChangeStepState(TimeOffStepState.REJECTED)
            }
            onClose={onCloseResolutionModal}
          />
        </View>
      )}
    </>
  );
}

export default ActionButtons;
