import { Dispatch } from 'redux';
import { showToast, ToastType } from 'src/common/util/show-toast';
import { performApiCall } from 'src/services/api';
import { transformAppRequest, transformApp, transformInstallAppRequest } from '../transformations';

export enum AppActionTypes {
  FETCH_APPS = 'apps/fetch_apps',
  FETCH_APP = 'apps/fetch_app',
  UPDATE_APP = 'apps/update_app',
  INSTALL_APP = 'apps/install_app',
  DELETE_APP = 'apps/delete_app',
  CLEAR_APP = 'apps/clear_app',
  SET_APP_LOADING = 'apps/app_loading',
  SET_APPS_LOADING = 'apps/apps_loading',
}

export const setAppsLoading = (isLoading: boolean) => (dispatch: Dispatch<any>) => {
  dispatch({
    type: AppActionTypes.SET_APPS_LOADING,
    payload: isLoading,
  });
};

export const setAppLoading = (isLoading: boolean) => (dispatch: Dispatch<any>) => {
  dispatch({
    type: AppActionTypes.SET_APP_LOADING,
    payload: isLoading,
  });
};

export const fetchApps = () => async (dispatch: Dispatch<any>) => {
  dispatch(setAppsLoading(true));

  try {
    const { data } = await performApiCall({
      path: '/apps',
      method: 'GET',
    });

    dispatch({
      type: AppActionTypes.FETCH_APPS,
      payload: data.map(transformApp),
    });
  } catch (err) {
    console.error(err);
  }

  dispatch(setAppsLoading(false));
};

export const fetchAppBySlug = (slug: string) => async (dispatch: Dispatch<any>) => {
  dispatch(setAppLoading(true));

  try {
    const { data } = await performApiCall({
      path: `/apps/${slug}`,
      method: 'GET',
    });

    dispatch({
      type: AppActionTypes.FETCH_APP,
      payload: transformApp(data),
    });
  } catch (err) {
    console.error(err);
  }

  dispatch(setAppLoading(false));
};

export const updateApp = (app: any) => async (dispatch: Dispatch<any>) => {
  dispatch(setAppLoading(true));

  try {
    const { data } = await performApiCall({
      path: `/apps/${app.slug}`,
      method: 'PUT',
      body: transformAppRequest(app),
    });

    dispatch({
      type: AppActionTypes.UPDATE_APP,
      payload: transformApp(data),
    });

    showToast('App is updated!', ToastType.Success);

    dispatch(fetchApps());
  } catch (err) {
    console.error(err);
  }

  dispatch(setAppLoading(false));
};

export const installAppBySlug = (app: any) => async (dispatch: Dispatch<any>) => {
  dispatch(setAppLoading(true));

  try {
    const { data } = await performApiCall({
      path: `/apps/${app.slug}/install`,
      method: 'PATCH',
      body: transformInstallAppRequest(app),
    });

    dispatch({
      type: AppActionTypes.INSTALL_APP,
      payload: transformApp(data),
    });

    showToast('App installing...', ToastType.Success);

    dispatch(fetchApps());
  } catch (err: any) {
    dispatch(setAppLoading(false));
    showToast(`${err}`, ToastType.Error);
    throw err;
  }

  dispatch(setAppLoading(false));
};

export const deleteApp = (appData: any) => async (dispatch: Dispatch<any>) => {
  dispatch(setAppLoading(true));

  try {
    await performApiCall({
      path: `/apps/${appData.slug}`,
      method: 'DELETE',
      body: { remove_app_data: appData.removeAppData },
    });

    dispatch({
      type: AppActionTypes.DELETE_APP,
      payload: {},
    });

    showToast('App disabled', ToastType.Success);

    dispatch(fetchApps());
  } catch (err: any) {
    dispatch(setAppLoading(false));
    showToast(`${err}`, ToastType.Error);
    throw err;
  }

  dispatch(setAppLoading(false));
};

export const clearCurrentApp = () => (dispatch: Dispatch<any>) => {
  dispatch({
    type: AppActionTypes.CLEAR_APP,
    payload: {},
  });
};
