import { useEffect, useMemo } from 'react';
import { FormProvider, useForm } 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 { moveApplicationToStage } from '../../../services';
import {
  type ApplicationStage,
  type MoveApplicantForwardFormValues,
  StageTypes,
} from '../../../types';
import { moveForwardApplicantFormResolver } from '../utils';

type MoveApplicantForwardModalProps = DialogProps & {
  stage: ApplicationStage;
  stages: ApplicationStage[];
  jobId: number;
};

export const MoveApplicantForwardModal = ({
  stage,
  jobId,
  stages,
  ...props
}: MoveApplicantForwardModalProps) => {
  const { t } = useLokaliseTranslation(['ats', 'validations', 'general']);
  const { enqueueSnackbar } = useSnackbar();
  const queryClient = useQueryClient();

  const isOfferStage = stage?.stageType === StageTypes.OFFER;

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

  const form = useForm<Partial<MoveApplicantForwardFormValues>>({
    defaultValues: {
      stage: {
        value: undefined,
        label: undefined,
      },
      date: new Date(),
    },
    mode: 'onChange',
    shouldUnregister: false,
    resolver,
  });

  const { mutate, isLoading } = useMutation({
    mutationFn: (values: Partial<MoveApplicantForwardFormValues>) => {
      const nextStageId = isOfferStage
        ? stages.find(stg => stg.stageType === StageTypes.OFFER_ACCEPTED)?.id
        : values?.stage?.value;

      if (!nextStageId) {
        throw new Error('invalid_next_stage');
      }

      return moveApplicationToStage({
        nextStageId,
        endDate: values.date || new Date(),
        jobId,
        applicationId: stage.applicationId,
      });
    },
    onSuccess: () => {
      enqueueSnackbar({
        title: t('job_application.actions.forward.success'),
        variant: 'success',
      });
      props.onClose();
      queryClient.invalidateQueries(
        applicantsKeys.applicationDetail(jobId, stage.applicationId),
      );
    },
    onError: () => {
      enqueueSnackbar({
        title: t('general:error_title'),
        variant: 'error',
      });
    },
  });

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

  useEffect(() => {
    if (stage) {
      const nextStage = stages.find(stg => stg.sortOrder > stage.sortOrder);
      if (nextStage) {
        form.reset(
          {
            stage: {
              value: nextStage.id,
              label: nextStage.name,
            },
            date: new Date(),
          },
          {
            keepDirty: false,
            keepIsValid: false,
            keepErrors: false,
          },
        );
      }
    }
  }, [stage, stages, form.reset]);

  return (
    <Dialog
      {...props}
      title={
        isOfferStage
          ? t('job_application.actions.forward.offer_accepted.title')
          : t('job_application.actions.forward.title')
      }
      onClose={props.onClose}
      body={
        <FormProvider {...form}>
          <Stack sx={{ gap: 2, flexDirection: 'column' }}>
            <Typography variant="globalS">
              {isOfferStage
                ? t(
                    'job_application.actions.forward.offer_accepted.description',
                  )
                : t('job_application.actions.forward.description')}
            </Typography>
            {!isOfferStage && (
              <FormAutocomplete
                name="stage"
                options={stages
                  .filter(
                    stg =>
                      stg.sortOrder > stage.sortOrder &&
                      stg.stageType !== StageTypes.OFFER_ACCEPTED,
                  )
                  .map(({ id, name }) => ({
                    label: name,
                    value: id,
                  }))}
                autocompleteProps={{
                  isServerFiltered: false,
                  multiple: false,
                  placeholder: t('general:select'),
                  label: requiredLabel(
                    t('job_candidates.new.fields.stage.label'),
                  ),
                  disableClearable: true,
                }}
              />
            )}
            <FormDatePicker
              name="date"
              inputProps={{
                label: requiredLabel(t('general:date_label')),
                enableClear: false,
                maxDate: getMaxTodayDate(),
                minDate: stage?.startDate
                  ? parseBackendDate(stage.startDate)
                  : undefined,
              }}
            />
          </Stack>
        </FormProvider>
      }
      primaryButtonProps={{
        ...props.primaryButtonProps,
        disabled: !form.formState.isValid || isLoading,
        loading: isLoading,
        children: t('job_candidates.actions.forward'),
        onClick: onSubmit,
      }}
      secondaryButtonProps={{
        ...props.secondaryButtonProps,
        children: t('general:cancel'),
        disabled: isLoading,
        onClick: props.onClose,
      }}
    />
  );
};
