import { UseMutationOptions, useMutation, useQueryClient } from 'react-query';
import api from '../../services/api';
import { AlertType, createToastProps } from '../../components/ui';
import { Toast } from 'native-base';
import useGetHeatPumpConfig from './useGetHeatPumpConfig';
import { HeatPumpConfig, Mode, HeatPumpState, OldConfiguration } from '../../models/heatpump';
import useGetHeatPumpState from './useGetHeatPumpState';

/**
 * Sets heat pump mode and updates cached heat pump state and configuration
 */
const useSetHeatPumpMode = (
  options?: Omit<UseMutationOptions<Mode, Response, Mode, OldConfiguration>, 'mutationFn'>,
) => {
  const client = useQueryClient();

  return useMutation<Mode, Response, Mode, OldConfiguration>({
    ...options,
    mutationFn: api.HeatPumpApi.setMode,
    onMutate: async newMode => {
      // Cancel any outgoing refetches
      // (so they don't overwrite our optimistic update)
      await client.cancelQueries(useGetHeatPumpConfig.key).catch(() => null);

      // Snapshot the previous configuration
      const oldConfiguration = client.getQueryData<HeatPumpConfig>(useGetHeatPumpConfig.key);

      // Optimistically update to the new configuration
      client.setQueryData(useGetHeatPumpConfig.key, {
        ...oldConfiguration,
        mode: newMode.mode,
      });

      return { oldConfiguration };
    },
    // If the mutation fails,
    // use the context returned from onMutate to roll back
    onError: (error, variables, ctx) => {
      if (ctx?.oldConfiguration) {
        client.setQueryData(useGetHeatPumpConfig.key, ctx.oldConfiguration);
      }
      Toast.show(createToastProps(AlertType.Error, 'Failed to change operating mode'));
      options?.onError && options.onError(error, variables, ctx);
    },
    onSuccess: (result, requestData, ctx) => {
      const oldState = client.getQueryData<HeatPumpState>(useGetHeatPumpState.key);
      client.setQueryData(useGetHeatPumpState.key, {
        ...oldState,
        mode: result.mode,
      });
      Toast.show(createToastProps(AlertType.Success, 'Operating mode successfully changed'));
      options?.onSuccess && options.onSuccess(result, requestData, ctx);
    },
  });
};

export default useSetHeatPumpMode;
