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

import { type AxiosError } from 'axios';
import Alert from '@material-hu/mui/Alert';
import DialogActions from '@material-hu/mui/DialogActions';
import DialogContent from '@material-hu/mui/DialogContent';
import DialogContentText from '@material-hu/mui/DialogContentText';
import DialogTitle from '@material-hu/mui/DialogTitle';
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 useGeneralError from 'src/hooks/useGeneralError';
import { createAcknowledgementsExchangesWindow } from 'src/services/acknowledgementsService';
import { type ResponseError } from 'src/types/services';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  validateDateRequiredRule,
  validateRequiredStringRule,
} from 'src/utils/validation';

import FormDatePicker from 'src/components/FormInputs/FormDatePicker';
import FormTextField from 'src/components/FormInputs/FormTextField';

type PeriodModalProps = {
  onClose: () => void;
  refetch: () => void;
};

export type PeriodFormValues = {
  name: string;
  startDate: Date | null;
  endDate: Date | null;
};

const PeriodModal = ({ onClose, refetch }: PeriodModalProps) => {
  const { t } = useLokaliseTranslation('acknowledgements');
  const { t: tLokalise } = useLokaliseTranslation();
  const { enqueueSnackbar } = useSnackbar();
  const showGeneralError = useGeneralError();

  const form = useForm<PeriodFormValues>({
    defaultValues: {
      name: '',
      startDate: null,
      endDate: null,
    },
    mode: 'onChange',
  });

  const {
    control,
    formState: { isValid },
  } = form;

  const [startDate, endDate] = useWatch({
    name: ['startDate', 'endDate'],
    control,
  });

  const mutation = useMutation(
    (values: PeriodFormValues) => createAcknowledgementsExchangesWindow(values),
    {
      onSuccess: response => {
        enqueueSnackbar({
          title: t('periods.created_success', {
            name: response.data.name,
          }),
          variant: 'success',
        });
        refetch();
        onClose();
      },
      onError: (err: AxiosError<ResponseError>) => {
        const code = err?.response?.data?.code;
        if (
          code &&
          [
            'EXCHANGE_WINDOW_ALREADY_EXISTS',
            'CONFLICTING_EXCHANGE_WINDOW_DATES',
          ].includes(code)
        ) {
          enqueueSnackbar({
            title: t(`periods.${code}`),
            variant: 'error',
          });
        } else {
          showGeneralError(err);
        }
      },
    },
  );

  const handleSave = form.handleSubmit(values => mutation.mutateAsync(values));

  return (
    <FormProvider {...form}>
      <DialogTitle>{t('periods.periods', { count: 1 })}</DialogTitle>
      <DialogContent>
        <DialogContentText>
          {t('periods.periods_instructions')}
        </DialogContentText>
        <FormTextField
          name="name"
          size="small"
          margin="normal"
          label={t('periods.period_name')}
          inputProps={{ maxLength: 30 }}
          rules={{ validate: validateRequiredStringRule }}
        />
        <Stack
          direction="row"
          sx={{ alignItems: 'center' }}
          spacing={2}
        >
          <FormDatePicker
            name="startDate"
            textFieldProps={{
              size: 'small',
              margin: 'normal',
              fullWidth: true,
              sx: { mb: 2 },
            }}
            datePickerProps={{
              label: tLokalise('general:from_date'),
              disablePast: true,
            }}
            validateRules={validateDateRequiredRule}
          />
          <FormDatePicker
            name="endDate"
            textFieldProps={{
              size: 'small',
              margin: 'normal',
              fullWidth: true,
            }}
            datePickerProps={{
              label: tLokalise('general:to_date'),
              minDate: startDate || undefined,
            }}
            isStart={false}
            validateRules={validateDateRequiredRule}
          />
        </Stack>
        {!(startDate && endDate) && (
          <Alert
            sx={{ mt: 2 }}
            severity="info"
          >
            {t('periods.must_choose_dates')}
          </Alert>
        )}
      </DialogContent>
      <DialogActions>
        <Button
          loading={mutation.isLoading}
          variant="contained"
          disabled={!isValid}
          onClick={handleSave}
        >
          {tLokalise('general:save')}
        </Button>
      </DialogActions>
    </FormProvider>
  );
};

export default PeriodModal;
