import { useFormikContext } from 'formik';
import React, { useCallback, useEffect, useState } from 'react';
import { StationErrorStateType } from '../FormStation.models';

/**
 * Component that watches for changes in the form validation state
 * and calls the callback with the current state.
 */
const ValidationWatcher: React.FC<{
  callback: (isValid: boolean) => void;
}> = ({ callback: isValid }) => {
  const formik = useFormikContext();
  useEffect(() => {
    isValid(formik.isValid);
  }, [formik.isValid, isValid]);
  return null;
};

/**
 * Cares for showing (and removing) validation errors.
 * @param stationError the currently showing error
 * @param setStationError the setter for the currently showing error
 * @returns
 * `setValidationError` - call this method to set the validation error.
 * `validationWatcher` - place this JSX somewhere inside the <Formik /> component children.
 */
export function useValidationError(
  stationError: StationErrorStateType | undefined,
  setStationError: React.Dispatch<
    React.SetStateAction<StationErrorStateType | undefined>
  >,
): {
  setValidationError: () => void;
  validationWatcher: JSX.Element;
} {
  // Track validation state of the from using the validationWatcher
  const [isValid, setIsValid] = useState<boolean>(true);

  useEffect(() => {
    // if the form became valid, remove the validation error
    if (isValid && stationError && stationError.type === 'validation') {
      setStationError(undefined);
    }
  }, [isValid, setStationError, stationError]);

  const setValidationError = useCallback((): void => {
    // set the validation error
    setStationError({
      title: 'Please fix the errors in the form to proceed.',
      type: 'validation',
    });
  }, [setStationError]);

  return {
    setValidationError,
    validationWatcher: (
      <ValidationWatcher callback={(valid) => setIsValid(valid)} />
    ),
  };
}
