import React, { useContext, useReducer, useState } from 'react';
import AuthContext from './AuthContext';
import authReducer from './AuthReducer';
import { USER_ACTIONS } from './AuthTypes';
import api from '../../utils/AxiosConfig';

// ### EXPORT useContext TO REDUCE NEEDED CODE IN CLIENT FILES
export function useAuth() {
  return useContext(AuthContext);
}

function AuthState({ children }) {
  // #################################
  // HOOKS
  // #################################
  // ### CURRENTUSER_ACTIONS
  // set default user for first page load and hard reloads (<CTRL +> F5)
  const initial_currenUser = JSON.parse(localStorage.getItem('user')) || null;
  const [currentUser, dispatchCurrentUser] = useReducer(authReducer, initial_currenUser);
  // ### ACCESSTOKEN
  const [accessToken, setAccessToken] = useState();

  // #################################
  // FUNCTIONS
  // #################################

  // ### LOGIN
  async function login(credentials) {
    let result = {};
    try {
      result = await api.post(
        '/users/login',
        credentials,
        { withCredentials: true }
      );
    } catch (error) {
      result = await api.post(
        '/users/adminlogin',
        credentials,
        { withCredentials: true }
      );
      // try to match output with normal user
      result.data.record = { ...result.data.admin, isAdmin: true };
    }
    // set current user to login and merge accessToken into currentUser
    dispatchCurrentUser({ type: USER_ACTIONS.SET, payload: { ...result.data.record } });
    setAccessToken(result.data.token);
    // TODO: don't store accessToken in localStorage, keep in memory only
    localStorage.setItem("accessToken", JSON.stringify(result.data.token));
    return result;
  }

  // ### HANDLE LOGOUT
  async function logout() {
    dispatchCurrentUser({ type: USER_ACTIONS.DROP });
    const result = await api.get(
      '/users/logout',
    );
    return result;
  }

  // ### REQUEST PASSWORD RESET
  function requestPasswordReset(email) {
    return api.post('/users/requestpasswordreset', { email });
  }

  // ### REQUEST PASSWORD RESET
  function requestEmailReset(email) {
    return api.post('/users/requestemailchange', { email });
  }

  // ### RETURN
  return (
    <AuthContext.Provider
      value={{
        login,
        currentUser,
        logout,
        requestPasswordReset,
        requestEmailReset,
        USER_ACTIONS,
        dispatchCurrentUser
      }}>
      {children}
    </AuthContext.Provider>
  );
};

export default React.memo(AuthState);