import { useMemo } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useMutation, useQueryClient } from 'react-query';

import { Stack, Typography } from '@material-hu/mui/index';

import Dialog, {
  type DialogProps,
} from '@material-hu/components/design-system/Dialog';
import FormAutocomplete from '@material-hu/components/design-system/Inputs/Autocomplete/form';
import FormDatePicker from '@material-hu/components/design-system/Inputs/DatePicker/form';
import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { useLokaliseTranslation } from 'src/utils/i18n';
import { requiredLabel } from 'src/utils/stringUtils';

import { getMaxTodayDate, parseBackendDate } from '../../../dateUtils';
import { applicantsKeys } from '../../../queries';
import { rejectApplicant } from '../../../services';
import {
  type ApplicationStage,
  type RejectApplicantFormValues,
  type RejectionReason,
  RejectionType,
} from '../../../types';
import { rejectApplicantFormResolver } from '../utils';

type RejectApplicantModalProps = DialogProps & {
  stage: ApplicationStage;
  jobId: number;
  rejectionReasons: RejectionReason[];
  onSuccess: () => void;
};

export const RejectApplicantModal = ({
  stage,
  jobId,
  rejectionReasons,
  onSuccess,
  ...props
}: RejectApplicantModalProps) => {
  const { t } = useLokaliseTranslation(['ats', 'validations', 'general']);
  const { enqueueSnackbar } = useSnackbar();
  const queryClient = useQueryClient();

  const resolver = useMemo(
    () => (values: Partial<RejectApplicantFormValues>) =>
      rejectApplicantFormResolver(values, t, stage),
    [t, stage],
  );

  const form = useForm<Partial<RejectApplicantFormValues>>({
    defaultValues: {
      rejectionType: undefined,
      reason: undefined,
      date: new Date(),
    },
    mode: 'onChange',
    shouldUnregister: false,
    resolver,
  });

  const selectedType = useWatch({
    control: form.control,
    name: 'rejectionType',
  });

  const rejectionTypeOptions = useMemo(
    () => [
      {
        value: RejectionType.INTERNAL_REJECTION,
        label: t('common.rejection_types.internal_rejection'),
      },
      {
        value: RejectionType.CANDIDATE_WITHDRAWAL,
        label: t('common.rejection_types.candidate_withdrawal'),
      },
    ],
    [t],
  );

  const filteredRejectionReasons = useMemo(
    () =>
      selectedType
        ? rejectionReasons.filter(r => r.type === selectedType.value)
        : [],
    [rejectionReasons, selectedType],
  );

  const { mutate, isLoading } = useMutation({
    mutationFn: (values: Partial<RejectApplicantFormValues>) =>
      rejectApplicant({ values, jobId, applicationId: stage.applicationId }),
    onSuccess: () => {
      enqueueSnackbar({
        title: t('job_application.actions.reject.alert.success'),
        variant: 'success',
      });
      props.onClose();
      queryClient.invalidateQueries(
        applicantsKeys.applicationDetail(jobId, stage.applicationId),
      );
      onSuccess();
    },
    onError: () => {
      enqueueSnackbar({
        title: t('general:error_title'),
        variant: 'error',
      });
    },
  });

  const onSubmit = form.handleSubmit(
    (values: Partial<RejectApplicantFormValues>) => {
      mutate(values);
    },
  );

  return (
    <Dialog
      {...props}
      title={t('job_application.actions.reject.title')}
      onClose={props.onClose}
      body={
        <FormProvider {...form}>
          <Stack sx={{ gap: 2, flexDirection: 'column' }}>
            <Typography variant="globalS">
              {t('job_application.actions.reject.description')}
            </Typography>
            <FormAutocomplete
              name="rejectionType"
              options={rejectionTypeOptions}
              autocompleteProps={{
                isServerFiltered: false,
                multiple: false,
                placeholder: t('general:select'),
                label: requiredLabel(t('job_application.actions.reject.type')),
                disableClearable: true,
                onInputChange: () => {
                  form.setValue('reason', undefined, { shouldValidate: false });
                },
              }}
            />
            <FormAutocomplete
              key={selectedType?.value ?? ''}
              name="reason"
              options={filteredRejectionReasons.map(reason => ({
                label: reason.name,
                value: reason.id,
              }))}
              autocompleteProps={{
                isServerFiltered: false,
                multiple: false,
                placeholder: t('general:select'),
                label: requiredLabel(
                  t('job_application.actions.reject.reason'),
                ),
                disableClearable: true,
                disabled: !selectedType,
              }}
            />
            <FormDatePicker
              name="date"
              inputProps={{
                label: requiredLabel(t('job_application.actions.reject.date')),
                enableClear: false,
                maxDate: getMaxTodayDate(),
                minDate: stage?.startDate
                  ? parseBackendDate(stage.startDate)
                  : undefined,
              }}
            />
          </Stack>
        </FormProvider>
      }
      primaryButtonProps={{
        ...props.primaryButtonProps,
        disabled: !form.formState.isValid || isLoading,
        children: t('job_candidates.actions.reject'),
        loading: isLoading,
        onClick: onSubmit,
      }}
      secondaryButtonProps={{
        ...props.secondaryButtonProps,
        children: t('general:cancel'),
        disabled: isLoading,
        onClick: props.onClose,
      }}
    />
  );
};
