import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; import type { ReactNode } from 'react'; import { mobileTelemetry, trackMobileError } from '@/lib/telemetry'; import { clearPlatformSession, loginPlatformSession, restorePlatformSession, type PlatformAuthUser, type StoredPlatformSession, } from '@/lib/platformAuth'; export interface MobileUserProfile { user_id: string; first_name?: string; last_name?: string; email?: string; role?: string; trade_enable?: boolean; } interface MobileAuthContextValue { session: StoredPlatformSession | null; user: PlatformAuthUser | null; profile: MobileUserProfile | null; loading: boolean; error: string | null; signIn: (email: string, password: string) => Promise<{ error?: string }>; signOut: () => Promise; invalidateSession: (reason: string) => Promise; refreshProfile: () => Promise; accessToken: string | null; } const MobileAuthContext = createContext(null); export function MobileAuthProvider({ children }: { children: ReactNode }) { const [session, setSession] = useState(null); const [user, setUser] = useState(null); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let active = true; async function bootstrap() { try { if (!active) { return; } const restored = await restorePlatformSession(); setSession(restored); setUser(restored?.user ?? null); if (restored?.user) { mobileTelemetry.trackEvent('info', 'auth', 'session_restored', { userId: restored.user.id, }); setProfile(buildProfile(restored.user)); setError(null); setLoading(false); } else { setLoading(false); } } catch (bootstrapError) { trackMobileError('auth', 'session_restore_failed', bootstrapError); setError(bootstrapError instanceof Error ? bootstrapError.message : 'Failed to restore session'); setLoading(false); } } void bootstrap(); return () => { active = false; }; }, []); function buildProfile(nextUser: PlatformAuthUser | null): MobileUserProfile | null { if (!nextUser?.id) { return null; } const displayName = String(nextUser.displayName || '').trim(); const parts = displayName ? displayName.split(/\s+/) : []; return { user_id: nextUser.id, first_name: parts[0] || undefined, last_name: parts.slice(1).join(' ') || undefined, email: nextUser.email, role: nextUser.role, trade_enable: true, }; } async function signIn(email: string, password: string) { setLoading(true); setError(null); try { const nextSession = await loginPlatformSession(email, password); setSession(nextSession); setUser(nextSession.user); setProfile(buildProfile(nextSession.user)); setError(null); mobileTelemetry.trackEvent('info', 'auth', 'sign_in_succeeded', { message: email, userId: nextSession.user.id, }); return {}; } catch (authError) { const message = authError instanceof Error ? authError.message : 'Sign in failed'; setError(message); trackMobileError('auth', 'sign_in_failed', authError, { email }); return { error: message }; } finally { setLoading(false); } } async function signOut() { setLoading(true); try { await clearPlatformSession(); mobileTelemetry.trackEvent('info', 'auth', 'sign_out_succeeded', { userId: user?.id, }); } finally { setProfile(null); setSession(null); setUser(null); setLoading(false); } } async function invalidateSession(reason: string) { setLoading(true); mobileTelemetry.trackEvent('warn', 'auth', 'session_invalidated', { message: reason, userId: user?.id, }); try { await clearPlatformSession(); } catch (invalidateError) { trackMobileError('auth', 'session_invalidation_signout_failed', invalidateError); } finally { setProfile(null); setSession(null); setUser(null); setError(reason); setLoading(false); } } async function refreshProfile() { if (!session) { return; } setLoading(true); try { const restored = await restorePlatformSession(); const nextUser = restored?.user ?? null; setSession(restored); setUser(nextUser); setProfile(buildProfile(nextUser)); setError(null); } catch (refreshError) { setError(refreshError instanceof Error ? refreshError.message : 'Failed to refresh profile'); trackMobileError('auth', 'profile_refresh_failed', refreshError, { userId: user?.id || 'unknown' }); } finally { setLoading(false); } } const value = useMemo( () => ({ session, user, profile, loading, error, signIn, signOut, invalidateSession, refreshProfile, accessToken: session?.accessToken ?? null, }), [session, user, profile, loading, error] ); return {children}; } export function useMobileAuth() { const context = useContext(MobileAuthContext); if (!context) { throw new Error('useMobileAuth must be used within a MobileAuthProvider'); } return context; }