import { STORAGE_KEYS } from '@/common/constants/storageKeys'; import { connectSync, disconnectAndClear } from '@/remote/database'; import * as SecureStore from 'expo-secure-store'; import { ReactNode, createContext, useContext, useEffect, useState } from 'react'; import { sendMagicCode, verifyMagicCode } from './api'; interface User { id: string; email: string; } interface AuthContextType { user: User | null; isLoading: boolean; signInWithEmail: (email: string) => Promise<{ success: boolean; message?: string }>; verifyOtp: (email: string, code: string) => Promise<{ success: boolean; message?: string }>; signOut: () => Promise; } const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { restoreSession(); }, []); useEffect(() => { if (user) { connectSync().catch(console.error); } }, [user?.id]); async function restoreSession() { try { const [token, userData] = await Promise.all([ SecureStore.getItemAsync(STORAGE_KEYS.SESSION_TOKEN), SecureStore.getItemAsync(STORAGE_KEYS.USER_DATA), ]); if (token && userData) { setUser(JSON.parse(userData) as User); } } catch (e) { console.error('Error restoring session:', e); } finally { setIsLoading(false); } } const signInWithEmail = async (email: string) => { return await sendMagicCode(email); }; const verifyOtp = async (email: string, code: string) => { const result = await verifyMagicCode(email, code); if (result.success && result.sessionToken && result.userId) { const newUser = { id: result.userId, email }; setUser(newUser); await SecureStore.setItemAsync(STORAGE_KEYS.SESSION_TOKEN, result.sessionToken); await SecureStore.setItemAsync(STORAGE_KEYS.USER_DATA, JSON.stringify(newUser)); } return result; }; const signOut = async () => { setUser(null); await disconnectAndClear(); await SecureStore.deleteItemAsync(STORAGE_KEYS.SESSION_TOKEN); await SecureStore.deleteItemAsync(STORAGE_KEYS.USER_DATA); }; return ( {children} ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }