import { useRouter } from 'next/router';
import React, { useContext } from 'react';
import { useLocalStorage } from 'react-use';
import { LoginMutation } from '../../graphql';

type UserData = LoginMutation['login'];

type AuthContextType = {
  authToken?: string | null;
  login: (userData: UserData, urlToRedirect?: string) => void;
  logout: (urlToRedirect?: string) => void;
  userData: UserData;
};

export const AuthContext = React.createContext<AuthContextType>({
  authToken: null,
  login: () => {},
  logout: () => {},
  userData: null,
});

export const AuthProvider: React.FC = (props) => {
  const router = useRouter();

  const [userData, setUserData] = useLocalStorage<UserData>('authToken');

  /**
   * Login the user.
   *
   * @param newUserData
   * @param urlToRedirect URL where user needs to be redirected after login.
   */
  const login = (newUserData: UserData, urlToRedirect = '/my-account') => {
    // Set the authToken, user ID and username in localStorage.
    setUserData(newUserData);

    // Redirect the user to the given URL.
    if (urlToRedirect != null) {
      router.push(urlToRedirect);
    }
  };

  /**
   * Logout the user.
   *
   * @param urlToRedirect URL where user needs to be redirected after logout.
   */
  const logout = (urlToRedirect = '/login') => {
    // Set auth data value in localStorage to empty.
    setUserData(undefined);

    // Redirect the user to the given URL.
    if (urlToRedirect != null) {
      router.push(urlToRedirect);
    }
  };

  return (
    <AuthContext.Provider
      value={{
        authToken: userData?.authToken,
        login,
        logout,
        userData: userData?.authToken == null ? null : userData,
      }}
      {...props}
    />
  );
};

export function useAuth() {
  const context = useContext(AuthContext);
  if (context == null) {
    throw new Error('useAuth must be used within a UIProvider');
  }
  return context;
}