import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQueryClient } from 'react-query';

import { isValid } from 'date-fns';
import { debounce } from 'lodash-es';
import Stack from '@material-hu/mui/Stack';

import CardContainer from '@material-hu/components/design-system/CardContainer';
import DatePicker from '@material-hu/components/design-system/Inputs/DatePicker';
import useSnackbar from '@material-hu/components/design-system/Snackbar';
import Switcher from '@material-hu/components/design-system/Switcher';

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

import { getMaxTodayDate, parseBackendDate } from '../../../dateUtils';
import { applicantsKeys } from '../../../queries';
import { updateOfferSentDate } from '../../../services';

type OfferSwitchProps = {
  date?: string;
  jobId: number;
  applicationId: number;
  stageId: number;
  sent?: boolean;
  stageStartDate?: string;
};

export const OfferSwitch = ({
  stageStartDate,
  date,
  jobId,
  applicationId,
  stageId,
  sent,
}: OfferSwitchProps) => {
  const { t } = useLokaliseTranslation(['ats', 'validations']);
  const [isSent, setIsSent] = useState(sent || false);
  const { enqueueSnackbar } = useSnackbar();
  const [dateInput, setDateInput] = useState<Date | null>(
    date ? parseBackendDate(date) : null,
  );
  const [isValidDate, setIsValidDate] = useState(true);

  const queryClient = useQueryClient();

  const { mutate: updateOfferDate } = useMutation(
    ({
      dateToUpdate,
      isOfferSent,
    }: {
      dateToUpdate: Date;
      isOfferSent: boolean;
    }) =>
      updateOfferSentDate({
        jobId,
        applicationId,
        date: dateToUpdate,
        stageId,
        isOfferSent,
      }),
    {
      onSuccess: (_, { isOfferSent }) => {
        if (isOfferSent) {
          enqueueSnackbar({
            title: t(
              'job_application.actions.offer.offer_letter.action.success',
            ),
            variant: 'success',
          });
        }

        queryClient.invalidateQueries(
          applicantsKeys.applicationDetail(jobId, applicationId),
        );
      },
      onError: () => {
        enqueueSnackbar({
          title: t('job_application.actions.offer.offer_letter.action.error'),
          variant: 'error',
        });
      },
    },
  );

  const minDate = useMemo(
    () => (stageStartDate ? parseBackendDate(stageStartDate) : undefined),
    [stageStartDate],
  );

  const debouncedOnChange = useMemo(
    () =>
      debounce((dateToCheck: Date | null) => {
        const normalizedDate = dateToCheck ? new Date(dateToCheck) : null;
        normalizedDate?.setHours(0, 0, 0, 0);
        const dateToUpdate = normalizedDate;

        // shouldn't be in the future and should not be before the stage start date if it exists
        if (
          dateToUpdate &&
          isValid(dateToUpdate) &&
          dateToUpdate.getTime() <= getMaxTodayDate().getTime() &&
          (!minDate || dateToUpdate.getTime() >= minDate.getTime())
        ) {
          setDateInput(dateToUpdate);
          updateOfferDate({ dateToUpdate, isOfferSent: true });
          setIsValidDate(true);
        } else {
          setIsValidDate(false);
        }
      }, 1000),
    [minDate, updateOfferDate],
  );

  const handleSwitchChange = (isOfferSent: boolean) => {
    setIsSent(isOfferSent);
    updateOfferDate({ dateToUpdate: dateInput || new Date(), isOfferSent });
  };

  useEffect(() => {
    return () => {
      debouncedOnChange.cancel();
    };
  }, [debouncedOnChange.cancel]);

  return (
    <CardContainer sx={{ width: '100%' }}>
      <Stack sx={{ gap: 2, flexDirection: 'column' }}>
        <Switcher
          value={isSent}
          onChange={handleSwitchChange}
          title={t('job_application.actions.offer.offer_letter.action.title')}
          sx={{
            '& .MuiTypography-root': {
              color: theme => theme.palette.new.text.neutral.default,
            },
          }}
        />
        {isSent && (
          <DatePicker
            value={dateInput || new Date()}
            label={t('job_application.actions.offer.offer_letter.action.label')}
            onChange={debouncedOnChange}
            helperText={t(
              'job_application.actions.offer.offer_letter.action.helper_text',
            )}
            minDate={minDate}
            maxDate={getMaxTodayDate()}
            error={!isValidDate}
            errorText={!isValidDate ? t('validations:invalid_date') : undefined}
          />
        )}
      </Stack>
    </CardContainer>
  );
};
