import { useContext, useEffect, useMemo, useRef } from 'react';

import {
  removeAllItems,
  saveAllItems,
  saveItem,
} from '@common/StorageHelper.ts';
import { TOKEN_KEY, USERINFO_KEY } from '@common/constants';
import {
  AuthContext,
  AuthState,
  RequiredUserInfo,
} from '@common/contexts/AuthContext.tsx';

const useAuth = (): {
  state: AuthState;
  actions: {
    login: (token: string, userInfo: RequiredUserInfo) => Promise<void>;
    logout: () => Promise<void>;
    update: (userInfo: RequiredUserInfo) => Promise<void>;
  };
} => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used in AuthProvider!');
  }

  const contextRef = useRef(context);
  useEffect(() => {
    contextRef.current = context;
  }, [context]);

  const authActions = useMemo(
    () => ({
      login: async (token: string, userInfo: RequiredUserInfo) => {
        await saveAllItems([
          { key: TOKEN_KEY, data: token },
          { key: USERINFO_KEY, data: JSON.stringify(userInfo) },
        ]);
        contextRef.current.dispatch({
          type: 'login',
          payload: {
            token: token,
            userInfo: userInfo,
          },
        });
      },
      logout: async () => {
        await removeAllItems([TOKEN_KEY, USERINFO_KEY]);
        contextRef.current.dispatch({
          type: 'logout',
          payload: undefined,
        });
      },
      update: async (userInfo: RequiredUserInfo) => {
        await saveItem(USERINFO_KEY, JSON.stringify(userInfo));
        contextRef.current.dispatch({ type: 'update', payload: userInfo });
      },
    }),
    [],
  );

  return { state: context.state, actions: authActions };
};

export { useAuth };
