import { createContext, useCallback, useContext, useMemo, useState } from 'react'; import type { ReactNode } from 'react'; const DEFAULT_AUTH_TOKEN_KEY = 'authToken'; const DEFAULT_REFRESH_TOKEN_KEY = 'refreshToken'; const DEFAULT_LEGACY_KEYS = ['auth_token', 'auth_user', 'token']; export type AuthState = { authToken: string | null; refreshToken: string | null; currentUser: TUser | null; }; export type AuthContextValue = AuthState & { setSession: (authToken: string, refreshToken: string, currentUser: TUser) => void; setCurrentUser: (currentUser: TUser | null) => void; clearSession: () => void; }; export type CreateAuthContextOptions = { authTokenKey?: string; refreshTokenKey?: string; legacyKeys?: string[]; }; export function createAuthContext(options: CreateAuthContextOptions = {}) { const authTokenKey = options.authTokenKey ?? DEFAULT_AUTH_TOKEN_KEY; const refreshTokenKey = options.refreshTokenKey ?? DEFAULT_REFRESH_TOKEN_KEY; const legacyKeys = options.legacyKeys ?? DEFAULT_LEGACY_KEYS; const AuthContext = createContext | undefined>(undefined); function readStoredSession(): AuthState { for (const key of legacyKeys) { localStorage.removeItem(key); } const authToken = localStorage.getItem(authTokenKey); const refreshToken = localStorage.getItem(refreshTokenKey); return { authToken, refreshToken, currentUser: null, }; } function AuthProvider({ children }: Readonly<{ children: ReactNode }>) { const [state, setState] = useState>(readStoredSession); const setSession = useCallback( (authToken: string, refreshToken: string, currentUser: TUser) => { localStorage.setItem(authTokenKey, authToken); localStorage.setItem(refreshTokenKey, refreshToken); setState({ authToken, refreshToken, currentUser }); }, [], ); const clearSession = useCallback(() => { localStorage.removeItem(authTokenKey); localStorage.removeItem(refreshTokenKey); setState({ authToken: null, refreshToken: null, currentUser: null }); }, []); const setCurrentUser = useCallback((currentUser: TUser | null) => { setState((prev) => ({ ...prev, currentUser })); }, []); const value = useMemo>( () => ({ ...state, setSession, setCurrentUser, clearSession, }), [state, setSession, setCurrentUser, clearSession], ); return {children}; } function useAuth() { const ctx = useContext(AuthContext); if (!ctx) { throw new Error('useAuth must be used within AuthProvider'); } return ctx; } return { AuthProvider, useAuth, AuthContext, }; }