import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';
import { useOutletContext } from 'react-router';

import { isEqual } from 'lodash-es';
import Stack from '@material-hu/mui/Stack';

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

import { queryClient } from 'src/config/react-query';
import useGeneralError from 'src/hooks/useGeneralError';
import useHugoUnsavedWarning from 'src/hooks/useUnsavedWarning/altHugo';
import * as regionService from 'src/services/regionsService';
import { useUsersPublicSearch } from 'src/services/usersQueries';
import { type RegionParam } from 'src/types/regions';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  getAssignmentTrackingProps,
  logEvent,
  LogEvents,
} from 'src/utils/logging';

import { usersKeys } from '../../Users/queries';
import PeopleStep from '../components/PeopleStep';
import { CollabSelection, type RegionOutletContext } from '../constants';
import { regionKeys } from '../queries';

function RegionCollaborators() {
  const { t } = useLokaliseTranslation('regions');
  const { regionData } = useOutletContext<RegionOutletContext>();
  const showGeneralError = useGeneralError();
  const { enqueueSnackbar } = useSnackbar();
  const { data: usersData } = useUsersPublicSearch({
    extraUseQueryParams: { enabled: true, keepPreviousData: true },
  });

  const parseCollaboratorsSelection = () => {
    if (regionData.userIds.length && usersData?.data.count) {
      return regionData.userIds.length === usersData.data.count
        ? CollabSelection.ALL_USERS
        : CollabSelection.TARGETED_USERS;
    }
    return CollabSelection.NONE;
  };

  const form = useForm({
    defaultValues: {
      userIds: regionData.userIds,
      regionsUserMode: parseCollaboratorsSelection(),
    },
    mode: 'onChange',
  });
  const {
    formState: { isValid },
    watch,
  } = form;

  const { regionsUserMode } = watch();

  const manuallySelectedAllCollabs =
    regionsUserMode === CollabSelection.TARGETED_USERS &&
    form.getValues('userIds').length === usersData?.data.count;

  const editRegionMutation = useMutation(
    (formValues: Pick<RegionParam, 'userIds' | 'regionsUserMode'>) =>
      regionService.updateRegion(regionData.id, { ...formValues }),
    {
      onSuccess: response => {
        const { userIds } = response.data;
        enqueueSnackbar({
          title: t('assign_success'),
          variant: 'success',
        });
        const parseManualSelection =
          userIds.length === usersData?.data.count
            ? CollabSelection.ALL_USERS
            : CollabSelection.TARGETED_USERS;

        const effectiveMode =
          regionsUserMode === CollabSelection.TARGETED_USERS
            ? parseManualSelection
            : regionsUserMode;

        logEvent(LogEvents.TIME_TRACKING_REGION_ASSIGNMENT_UPDATED, {
          regionId: regionData.id,
          ...getAssignmentTrackingProps(
            effectiveMode,
            userIds,
            usersData?.data.count ?? 0,
          ),
        });

        form.reset({
          userIds,
          regionsUserMode:
            regionsUserMode === CollabSelection.TARGETED_USERS
              ? parseManualSelection
              : regionsUserMode,
        });
        queryClient.setQueryData(regionKeys.region(regionData.id), response);
        queryClient.invalidateQueries(usersKeys.regionUsers());
      },
      onError: err => {
        showGeneralError(err, t('assign_error'));
      },
    },
  );

  const handleSubmit = () => {
    const peopleValues = form.getValues();
    const valuesToSubmit: Pick<RegionParam, 'userIds' | 'regionsUserMode'> = {
      ...peopleValues,
    };
    if (regionsUserMode === CollabSelection.ALL_USERS) {
      valuesToSubmit.userIds = null as any;
    }
    // User selected manually all the available collaborators
    if (manuallySelectedAllCollabs) {
      valuesToSubmit.userIds = null as any;
      valuesToSubmit.regionsUserMode = CollabSelection.ALL_USERS;
    }
    if (regionsUserMode === CollabSelection.NONE) {
      valuesToSubmit.userIds = [];
      delete valuesToSubmit.regionsUserMode;
    }
    editRegionMutation.mutate(valuesToSubmit);
  };

  const modifiedSelectionMode = manuallySelectedAllCollabs
    ? parseCollaboratorsSelection() !== CollabSelection.ALL_USERS
    : regionsUserMode !== parseCollaboratorsSelection();
  const formIsDirty =
    !isEqual(form.getValues('userIds').sort(), regionData.userIds.sort()) ||
    modifiedSelectionMode;

  // Since there's already an option for "no assigned collabs" the submit will be disabled
  // in case the user chooses the option "target users" and there's no user selected
  const formIsValid =
    regionsUserMode === CollabSelection.TARGETED_USERS
      ? form.getValues('userIds').length > 0
      : isValid;

  useEffect(() => {
    if (usersData?.data) {
      form.setValue('regionsUserMode', parseCollaboratorsSelection());
    }
  }, [usersData]);

  const { modal: UnsavedChangesModal, blocker } = useHugoUnsavedWarning({
    modalProps: {
      title: t('WISH_SAVE_CHANGES_TITLE'),
      body: t('WISH_SAVE_CHANGES_BODY'),
      primaryButtonProps: {
        children: t('GENERAL:SAVE'),
        onClick: () => {
          blocker?.reset?.();
          UnsavedChangesModal?.closeModal();
          handleSubmit();
        },
      },
      secondaryButtonProps: {
        children: t('QUIT_WITHOUT_SAVING'),
        onClick: () => {
          UnsavedChangesModal?.closeModal();
          blocker?.proceed?.();
        },
      },
    },
    shouldBlock: formIsDirty,
  });

  return (
    <>
      {UnsavedChangesModal.modal}
      <FormProvider {...form}>
        <Stack
          sx={{
            flex: 1,
            justifyContent: 'space-between',
            pb: 10,
          }}
        >
          <PeopleStep
            isLoading={editRegionMutation.isLoading}
            isEdit
          />
        </Stack>
        <Stack
          sx={{
            position: 'fixed',
            bottom: 0,
            left: 0,
            right: 0,
            flexDirection: 'row',
            justifyContent: 'end',
            backgroundColor: theme => theme.palette.background.paper,
            boxShadow: theme => theme.shadows[2],
            py: 2,
            px: '18%',
            width: '100%',
            zIndex: 1000,
          }}
        >
          <Button
            variant="primary"
            size="large"
            disabled={
              !formIsDirty || !formIsValid || editRegionMutation.isLoading
            }
            onClick={handleSubmit}
          >
            {t('GENERAL:SAVE')}
          </Button>
        </Stack>
      </FormProvider>
    </>
  );
}

export default RegionCollaborators;
