import { useFormikContext } from 'formik';
import { useEffect, useRef } from 'react';

interface SaveOnDemandProps {
  /** If set to true, will prevent form submission when navigating away. (default: false) */
  isSubmitting?: boolean;
  /** Callback that will be called when the form is invalid */
  onFormInvalid?: () => void;

  registerSaveCallback?: (callback: () => Promise<void>) => void;
}

export const SaveOnDemand: React.FC<SaveOnDemandProps> = ({
  onFormInvalid,
  isSubmitting,
  registerSaveCallback,
}) => {
  const { submitForm, dirty, isValid } = useFormikContext();
  const canSubmit = useRef(true);

  useEffect(() => {
    const saveCallback = async (): Promise<void> => {
      if (!dirty) {
        return;
      }

      if (!isValid) {
        onFormInvalid?.();
        throw new Error('Form is not valid');
      }

      try {
        if (!isSubmitting && canSubmit.current) {
          canSubmit.current = false;
          await submitForm();
          canSubmit.current = true;
        }
      } catch (error) {
        canSubmit.current = true;
        throw error;
      }
    };

    registerSaveCallback?.(saveCallback);
  }, [
    canSubmit,
    dirty,
    isSubmitting,
    isValid,
    onFormInvalid,
    registerSaveCallback,
    submitForm,
  ]);

  return null;
};
