import { createContext, useContext, useState, useCallback, useEffect, type ReactNode, } from 'react'; import api, { setAccessToken } from '../api/client'; interface User { id: string; email: string; firstName: string; lastName: string; avatar?: string | null; phone?: string | null; mobile?: string | null; street?: string | null; postalCode?: string | null; city?: string | null; role: string; twoFactorEnabled: boolean; } interface AuthContextType { user: User | null; isAuthenticated: boolean; isLoading: boolean; login: (email: string, password: string, totpCode?: string) => Promise; loginWithToken: (accessToken: string) => Promise; logout: () => Promise; refreshUser: () => Promise; } interface LoginResult { success: boolean; requiresTwoFactor?: boolean; error?: string; } const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // Beim Start: Silent Refresh versuchen useEffect(() => { const initAuth = async () => { try { const { data } = await api.post<{ accessToken: string }>( '/auth/refresh', ); setAccessToken(data.accessToken); // User-Profil laden const profileResponse = await api.get('/users/me'); setUser(profileResponse.data); } catch { // Nicht eingeloggt - normal setAccessToken(null); setUser(null); } finally { setIsLoading(false); } }; initAuth(); }, []); const login = useCallback( async ( email: string, password: string, totpCode?: string, ): Promise => { try { const { data } = await api.post<{ accessToken?: string; user?: User; requiresTwoFactor?: boolean; }>('/auth/login', { email, password, totpCode }); if (data.requiresTwoFactor) { return { success: false, requiresTwoFactor: true }; } if (data.accessToken && data.user) { setAccessToken(data.accessToken); setUser(data.user); return { success: true }; } return { success: false, error: 'Unerwartete Antwort vom Server' }; } catch (err: unknown) { const error = err as { response?: { data?: { message?: string } } }; return { success: false, error: error.response?.data?.message ?? 'Login fehlgeschlagen', }; } }, [], ); /** * SSO-Login: Access-Token direkt setzen und User-Profil laden. * Wird von SsoCallbackPage aufgerufen. */ const loginWithToken = useCallback(async (token: string) => { setAccessToken(token); const { data } = await api.get('/users/me'); setUser(data); }, []); const refreshUser = useCallback(async () => { try { const { data } = await api.get('/users/me'); setUser(data); } catch { // Fehler ignorieren - User bleibt unverändert } }, []); const logout = useCallback(async () => { try { await api.post('/auth/logout'); } catch { // Fehler ignorieren } finally { setAccessToken(null); setUser(null); } }, []); return ( {children} ); } export function useAuth(): AuthContextType { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth muss innerhalb von AuthProvider verwendet werden'); } return context; }