import { createContext, useContext, useEffect, useState, type ReactNode } from 'react' import { authApi, getStoredSession, profileApi, saveSession, subscribeToSessionChanges, } from '../api/client' import type { AuthCredentials, AuthResponse, AuthSession, RegisterPayload, User } from '../types/models' interface AuthContextValue { session: AuthSession | null user: User | null isAuthenticated: boolean isSiteAdmin: boolean initializing: boolean login: (payload: AuthCredentials) => Promise register: (payload: RegisterPayload) => Promise logout: () => Promise refreshProfile: () => Promise setCurrentUserProfile: (profile: User) => AuthSession | null } interface AuthProviderProps { children: ReactNode } const AuthContext = createContext(null) const SITE_ADMIN_ROLES = new Set(['Site Admin', 'Admin']) export function AuthProvider({ children }: AuthProviderProps) { const [session, setSession] = useState(() => getStoredSession()) const [initializing, setInitializing] = useState(() => Boolean(getStoredSession())) function setCurrentUserProfile(profile: User): AuthSession | null { const currentSession = getStoredSession() if (!currentSession) { return null } return saveSession({ ...currentSession, user: profile, }) } async function refreshProfile(): Promise { const currentSession = getStoredSession() if (!currentSession) { return null } const profile = await profileApi.getProfile() setCurrentUserProfile(profile) return profile } useEffect(() => subscribeToSessionChanges(setSession), []) useEffect(() => { let cancelled = false async function syncStoredSession() { const existingSession = getStoredSession() if (!existingSession) { if (!cancelled) { setInitializing(false) } return } try { const profile = await profileApi.getProfile() if (!cancelled) { setCurrentUserProfile(profile) } } catch { // The API client already clears invalid sessions after a failed refresh. } finally { if (!cancelled) { setInitializing(false) } } } syncStoredSession() return () => { cancelled = true } }, []) const user = session?.user ?? null const userRoles = Array.isArray(user?.roles) ? user.roles : [] const value = { session, user, isAuthenticated: Boolean(session?.accessToken), isSiteAdmin: userRoles.some(role => SITE_ADMIN_ROLES.has(role)), initializing, login: authApi.login, register: authApi.register, logout: authApi.logout, refreshProfile, setCurrentUserProfile, } return {children} } export function useAuth() { const value = useContext(AuthContext) if (!value) { throw new Error('useAuth must be used inside an AuthProvider.') } return value }