import browserHistory from '@history';
import _ from '@lodash';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import settingsConfig from 'app/configs/settingsConfig';
import { showMessage } from 'app/store/fuse/messageSlice';
import { setInitialSettings } from 'app/store/fuse/settingsSlice';
import { authService } from '../services';

export const setUser = createAsyncThunk('user/setUser', async (user) => {
  // You can redirect the logged-in user to a specific route depending on his role
  if (user.loginRedirectUrl) {
    settingsConfig.loginRedirectUrl = user.loginRedirectUrl; // for example 'apps/academy'
  }

  return _.merge({}, initialState, user);
});

export const updateUserSettings = createAsyncThunk(
  'user/updateSettings',
  async (settings, { dispatch, getState }) => {
    const { user } = getState();
    const newUser = _.omit(_.merge({}, user, { data: { ...settings } }), 'history');

    dispatch(updateUserData(newUser))
      .then(() => {
        dispatch(showMessage({ message: 'User data saved' }));
      })
      .catch((error) => {
        dispatch(showMessage({ message: error.message }));
      });

    return newUser;
  }
);

export const updateUserFavorites = createAsyncThunk(
  'user/updateFavorites',
  async (item, { dispatch, getState }) => {
    const { user } = getState();
    const hasItemInFavorites = user.favorites.find(
      (favoriteItem) => favoriteItem.id === item.id && item.favorite
    );
    const hasItemInHistory = user.history.find((history) => history.id === item.id);

    const favorites = hasItemInFavorites
      ? user.favorites.filter((favorite) => favorite.id !== item.id)
      : [...user.favorites, { ...item, favorite: true }];

    if (hasItemInHistory) {
      const history = user.history.map((historyItem) => {
        if (historyItem.id === item.id) {
          return { ...historyItem, favorite: !hasItemInFavorites };
        }

        return historyItem;
      });

      dispatch(updateUserHistory(history));
    }

    const newUserData = _.omit({ ...user, favorites }, 'history');

    dispatch(updateUserData(newUserData))
      .then(() => {
        if (hasItemInFavorites) {
          dispatch(showMessage({ message: 'The property is removed from favorites' }));
        } else {
          dispatch(showMessage({ message: 'The property is saved to favorites' }));
        }
      })
      .catch((error) => {
        dispatch(showMessage({ message: error.message }));
      });

    return favorites;
  }
);

export const updateUserHistory = (history) => (dispatch) => {
  localStorage.setItem('user', JSON.stringify({ history }));
  dispatch(userHistoryUpdated(history));
};

export const logoutUser = () => async (dispatch, getState) => {
  const { user } = getState();

  if (!user.role || user.role.length === 0) {
    // is guest
    return null;
  }

  browserHistory.push({
    pathname: '/',
  });

  dispatch(setInitialSettings());

  return dispatch(userLoggedOut());
};

export const updateUserData = (user) => async (dispatch, getState) => {
  if (!user.role || user.role.length === 0) {
    // is guest
    return;
  }

  // eslint-disable-next-line consistent-return
  return authService.updateUserData(user);
};

const initialState = {
  role: [], // guest
  data: {
    displayName: 'John Doe',
    email: 'johndoe@withinpixels.com',
  },
  history: [],
  favorites: [],
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    userLoggedOut: (state, action) => initialState,
    userHistoryUpdated: (state, action) => ({ ...state, history: action.payload }),
  },
  extraReducers: {
    [updateUserSettings.fulfilled]: (state, action) => action.payload,
    [updateUserFavorites.fulfilled]: (state, action) => ({ ...state, favorites: action.payload }),
    [setUser.fulfilled]: (state, action) => action.payload,
  },
});

export const { userLoggedOut, userHistoryUpdated } = userSlice.actions;

export const selectUser = ({ user }) => user;

export const selectUserHistory = ({ user }) => user.history;

export const selectUserFavorites = ({ user }) => user.favorites;

export default userSlice.reducer;
