import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; import api from '../services/api'; import { AuthResponse, User } from '../types'; interface AuthContextType { user: User | null; serverAddress: string | null; token: string | null; isAuthenticated: boolean; isLoading: boolean; canCreate: boolean; login: (serverAddress: string, identity: string, password: string) => Promise; logout: () => Promise; } const AuthContext = createContext(undefined); export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [user, setUser] = useState(null); const [serverAddress, setServerAddress] = useState(null); const [token, setToken] = useState(null); const [isLoading, setIsLoading] = useState(true); const [canCreate, setCanCreate] = useState(null); useEffect(() => { loadAuth(); }, []); const clearSession = useCallback(async () => { await AsyncStorage.multiRemove(['auth_token', 'auth_user', 'auth_can_create']); api.clearToken(); api.clearCanCreate(); setToken(null); setUser(null); setCanCreate(null); }, []); useEffect(() => { api.setUnauthorizedHandler(clearSession); return () => { api.setUnauthorizedHandler(null); }; }, [clearSession]); const loadAuth = async () => { try { const storedToken = await AsyncStorage.getItem('auth_token'); const storedUser = await AsyncStorage.getItem('auth_user'); const storedServerAddress = await AsyncStorage.getItem('auth_server_address'); const storedCanCreate = await AsyncStorage.getItem('auth_can_create'); if (storedCanCreate) { setCanCreate(storedCanCreate === 'true'); } if (storedToken && storedUser) { setToken(storedToken); api.setToken(storedToken); setUser(JSON.parse(storedUser)); } if (storedServerAddress) { setServerAddress(storedServerAddress); api.setAddress(storedServerAddress + '/api'); } } catch (error) { console.error('Failed to load auth', error); } finally { setIsLoading(false); } }; const login = async (serverAddress: string, identity: string, password: string) => { try { const response: AuthResponse = await api.authenticate(serverAddress, identity, password); await AsyncStorage.setItem('auth_token', response.token); await AsyncStorage.setItem('auth_user', JSON.stringify(response.record)); await AsyncStorage.setItem('auth_server_address', serverAddress); await AsyncStorage.setItem('auth_can_create', api.getCanCreate() ? 'true' : 'false'); setToken(response.token); setUser(response.record); setServerAddress(serverAddress); setCanCreate(api.getCanCreate() || false); } catch (error) { throw error; } }; const logout = async () => { try { await clearSession(); } catch (error) { console.error('Failed to logout', error); } }; return ( {children} ); }; export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };