import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useParams } from 'react-router';

import { useDrawer } from '@material-hu/hooks/useDrawer';
import { useModal } from '@material-hu/hooks/useModal';
import {
  IconBuildingSkyscraper,
  IconUsers,
  IconUsersGroup,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';
import { fadeIn } from '@material-hu/utils/animations';

import StateCard from '@material-hu/components/composed-components/StateCard';
import Button from '@material-hu/components/design-system/Buttons/Button';
import Dialog from '@material-hu/components/design-system/Dialog';
import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import useSnackbar from '@material-hu/components/design-system/Snackbar';
import Title from '@material-hu/components/design-system/Title';

import { employeeLifecycleKeys } from 'src/pages/dashboard/EmployeeLifecycle/queries';
import {
  createProcessAssignment,
  deleteProcessAssignment,
  editProcessAssignment,
  getProcessAssignments,
} from 'src/pages/dashboard/EmployeeLifecycle/services';
import { useLokaliseTranslation } from 'src/utils/i18n';

import AudienceUsersList from 'src/components/Audience/AudienceUsersList';
import SelectionCriteriaCard from 'src/components/Audience/components/SelectionCriteriaCard';

import StepLayout from '../../StepLayout';

import CriteriaSelectionDropdown from './components/CriteriaSelectionDropdown';
import TotalAssignmentButton from './components/TotalAssignmentButton';
import useAllSelection from './hooks/useAllSelection';
import useIndividualSelection from './hooks/useIndividualSelection';
import useSegmentationSelection from './hooks/useSegmentationSelection';
import { AssignmentStepProps } from './types';

const AssignmentStep = ({
  onPreviousStep,
  onNextStep,
  onSubmitting,
  onError,
  onSubmitted,
  processId: inheritedProcessId,
  sx,
}: AssignmentStepProps) => {
  const { t } = useLokaliseTranslation('employee_lifecycle');
  const { enqueueSnackbar } = useSnackbar();
  const { processId: paramsProcessId } = useParams<{ processId: string }>();
  const queryClient = useQueryClient();
  const processId = inheritedProcessId || paramsProcessId || '';

  const assignmentsRequest = useQuery({
    queryKey: employeeLifecycleKeys.processAssignments(processId),
    queryFn: () => getProcessAssignments(processId),
    enabled: !!processId,
  });

  const segmentationGroups: Record<string, number[]> = {};

  const assignmentsCount = assignmentsRequest?.data?.length || 0;

  assignmentsRequest?.data?.forEach(assignment => {
    if (assignment.assignment.type === 'SEGMENTATION') {
      for (const key of Object.keys(assignment.assignment.segmentation)) {
        const groupId = Number(key);
        if (!segmentationGroups[groupId]) {
          segmentationGroups[groupId] = [];
        }
        segmentationGroups[groupId].push(
          ...assignment.assignment.segmentation[groupId],
        );
      }
    }
  });

  const { drawer: selectedUsersDrawer, showDrawer: showSelectedUsersDrawer } =
    useDrawer(
      AudienceUsersList,
      {
        title: t('process_stepper.steps.assignment.total_reach'),
        hasBackButton: true,
      },
      {
        processId,
      },
    );

  const createAssignmentsMutation = useMutation({
    mutationKey: employeeLifecycleKeys.processAssignments(processId),
    mutationFn: createProcessAssignment,
    onMutate: () => {
      onSubmitting?.();
    },
    onError: error => {
      onError?.(error);
      enqueueSnackbar({
        variant: 'error',
        title: t('process_stepper.steps.assignment.actions.create.error'),
      });
    },
    onSuccess: () => {
      enqueueSnackbar({
        variant: 'success',
        title: t('process_stepper.steps.assignment.actions.create.success'),
      });
      closeIndividualSelectionDrawer();
      closeSegmentationSelectionDrawer();
      closeAllSelectionDrawer();
      queryClient.invalidateQueries(employeeLifecycleKeys.all());
      onSubmitted?.();
    },
  });

  const editAssignmentsMutation = useMutation({
    mutationKey: employeeLifecycleKeys.processAssignments(processId),
    mutationFn: editProcessAssignment,
    onMutate: () => {
      onSubmitting?.();
    },
    onError: error => {
      onError?.(error);
      enqueueSnackbar({
        variant: 'error',
        title: t('process_stepper.steps.assignment.actions.edit.error'),
      });
    },
    onSuccess: () => {
      enqueueSnackbar({
        variant: 'success',
        title: t('process_stepper.steps.assignment.actions.edit.success'),
      });
      closeIndividualSelectionDrawer();
      closeSegmentationSelectionDrawer();
      closeAllSelectionDrawer();
      queryClient.invalidateQueries(employeeLifecycleKeys.all());
      onSubmitted?.();
    },
  });

  const deleteAssignmentMutation = useMutation({
    mutationFn: deleteProcessAssignment,
    onError: error => {
      enqueueSnackbar({
        variant: 'error',
        title: t('process_stepper.steps.assignment.actions.delete.error'),
      });
      console.error(error);
    },
    onSuccess: () => {
      enqueueSnackbar({
        variant: 'success',
        title: t('process_stepper.steps.assignment.actions.delete.success'),
      });
      queryClient.invalidateQueries(employeeLifecycleKeys.all());
      confirmDeletionModal.closeModal();
    },
  });

  const confirmDeletionModal = useModal(Dialog, { maxWidth: 'sm' });

  const handleAssignmentDelete = ({
    assignmentId,
    processId: _processId,
  }: {
    assignmentId: number;
    processId: number;
  }): Promise<undefined> => {
    confirmDeletionModal.showModal({
      title: t(
        'process_stepper.steps.assignment.actions.delete.confirm_dialog.title',
      ),
      textBody: t(
        'process_stepper.steps.assignment.actions.delete.confirm_dialog.description',
      ),
      primaryButtonProps: {
        children: t(
          'process_stepper.steps.assignment.actions.delete.confirm_dialog.confirm',
        ),
        onClick: () => {
          deleteAssignmentMutation.mutate({
            assignmentId,
            processId: _processId,
          });
        },
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        onClick: () => {
          confirmDeletionModal.closeModal();
        },
      },
    });

    return Promise.resolve(undefined);
  };

  const generalLoading =
    assignmentsRequest?.isLoading ||
    createAssignmentsMutation?.isLoading ||
    editAssignmentsMutation?.isLoading ||
    deleteAssignmentMutation?.isLoading;

  const canContinue = (assignmentsRequest.data?.length || 0) > 0;

  const {
    SummaryCard: IndividualSummaryCard,
    individualSelectionDrawer,
    closeIndividualSelectionDrawer,
    showIndividualSelectionDrawer,
  } = useIndividualSelection({
    onConfirm: values => {
      if ('assignmentId' in values && !Number.isNaN(values.assignmentId)) {
        return editAssignmentsMutation.mutateAsync(values);
      }
      return createAssignmentsMutation.mutateAsync(values);
    },
    onDelete: handleAssignmentDelete,
    processId: processId,
    disabled: false,
  });

  const {
    SummaryCard: SegmentationSummaryCard,
    segmentationSelectionDrawer,
    closeSegmentationSelectionDrawer,
    showSegmentationSelectionDrawer,
  } = useSegmentationSelection({
    onConfirm: values => {
      if ('assignmentId' in values && !Number.isNaN(values.assignmentId)) {
        return editAssignmentsMutation.mutateAsync(values);
      }
      return createAssignmentsMutation.mutateAsync(values);
    },
    onDelete: handleAssignmentDelete,
    processId: processId,
    disabled: false,
  });

  const {
    SummaryCard: AllSummaryCard,
    allSelectionDrawer,
    closeAllSelectionDrawer,
    showAllSelectionDrawer,
  } = useAllSelection({
    onConfirm: values => {
      if ('assignmentId' in values && !Number.isNaN(values.assignmentId)) {
        return editAssignmentsMutation.mutateAsync(values);
      }
      return createAssignmentsMutation.mutateAsync(values);
    },
    onDelete: handleAssignmentDelete,
    processId: processId,
    disabled: false,
  });

  const assignmentsIds = assignmentsRequest?.data
    ?.map(assignment =>
      [assignment.assignment.type, assignment.assignmentId].join('-'),
    )
    .join('-');

  return (
    <StepLayout
      sx={sx}
      footer={
        <>
          <Button
            variant="tertiary"
            size="large"
            sx={{
              animation: `${fadeIn} 125ms ease-in-out backwards`,
            }}
            onClick={onPreviousStep}
          >
            {t('general:back')}
          </Button>
          <Button
            variant="primary"
            size="large"
            onClick={onNextStep}
            disabled={!canContinue}
            loading={generalLoading}
          >
            {t('general:continue')}
          </Button>
        </>
      }
    >
      {confirmDeletionModal.modal}
      <Stack sx={{ gap: 5, px: 2, flex: 1 }}>
        <Stack
          sx={{ flexDirection: 'row', gap: 2, justifyContent: 'space-between' }}
        >
          <Title
            title={t('process_stepper.steps.assignment.title')}
            description={t('process_stepper.steps.assignment.description')}
            variant="M"
          />
          {assignmentsCount > 0 && (
            <TotalAssignmentButton
              processId={processId}
              key={assignmentsIds}
              onClick={showSelectedUsersDrawer}
            />
          )}
        </Stack>
        <Stack sx={{ gap: 2, flex: 1 }}>
          {assignmentsRequest.isError && !assignmentsRequest?.isLoading && (
            <StateCard
              slotProps={{
                title: {
                  title: t(
                    'process_stepper.steps.assignment.error_fetching_title',
                  ),
                  description: t(
                    'process_stepper.steps.assignment.error_fetching_description',
                  ),
                },
              }}
            />
          )}

          {assignmentsRequest?.isLoading && (
            <Stack
              sx={{
                gap: 2,
                flex: 1,
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <HuSpinner centered />
              <Typography
                variant="globalS"
                align="center"
              >
                {t('process_stepper.steps.assignment.loading')}
              </Typography>
            </Stack>
          )}

          {!assignmentsRequest?.isLoading &&
            !assignmentsRequest?.isError &&
            assignmentsRequest?.data?.map(assignment => {
              if (assignment.assignment.type === 'DIRECT') {
                return (
                  <IndividualSummaryCard
                    key={assignment.assignmentId}
                    assignmentId={assignment.assignmentId}
                    processId={Number(processId)}
                    assignment={assignment.assignment}
                    disabled={false}
                  />
                );
              }

              if (assignment.assignment.type === 'SEGMENTATION') {
                return (
                  <SegmentationSummaryCard
                    key={assignment.assignmentId}
                    assignmentId={assignment.assignmentId}
                    processId={Number(processId)}
                    assignment={assignment.assignment}
                    disabled={false}
                  />
                );
              }

              if (assignment.assignment.type === 'ALL') {
                return (
                  <AllSummaryCard
                    key={assignment.assignmentId}
                    assignmentId={assignment.assignmentId}
                    processId={Number(processId)}
                    assignment={assignment.assignment}
                    disabled={false}
                  />
                );
              }
            })}

          {!assignmentsRequest?.isLoading &&
            !assignmentsRequest?.isError &&
            !!assignmentsCount && (
              <CriteriaSelectionDropdown
                assignments={assignmentsRequest?.data ?? []}
                showIndividualSelectionDrawer={showIndividualSelectionDrawer}
                showSegmentationSelectionDrawer={
                  showSegmentationSelectionDrawer
                }
                showAllSelectionDrawer={showAllSelectionDrawer}
                sx={{ marginTop: 1 }}
              />
            )}

          {!assignmentsRequest?.isLoading &&
            !assignmentsCount &&
            !assignmentsRequest?.isError && (
              <>
                <SelectionCriteriaCard
                  onClick={showIndividualSelectionDrawer}
                  Icon={IconUsers}
                  title={t('audience:individual_users_title')}
                  description={t('audience:individual_users_description')}
                  sx={{ animationDelay: `${0 * 25}ms` }}
                />
                <SelectionCriteriaCard
                  onClick={showSegmentationSelectionDrawer}
                  Icon={IconUsersGroup}
                  title={t('audience:segmented_users_title')}
                  description={t('audience:segmented_users_description')}
                  label={t('audience:automatic_assignment')}
                  sx={{ animationDelay: `${1 * 25}ms` }}
                />
                <SelectionCriteriaCard
                  onClick={showAllSelectionDrawer}
                  Icon={IconBuildingSkyscraper}
                  title={t('audience:all_users_title')}
                  description={t('audience:all_users_description')}
                  label={t('audience:automatic_assignment')}
                  sx={{ animationDelay: `${2 * 25}ms` }}
                />
              </>
            )}
          {individualSelectionDrawer}
          {segmentationSelectionDrawer}
          {allSelectionDrawer}
          {selectedUsersDrawer}
        </Stack>
      </Stack>
    </StepLayout>
  );
};

export default AssignmentStep;
