import React, { createContext, useState, useEffect, ReactNode } from "react"; import { User } from "../types"; export interface SignInOptions { callbackUrl?: string; redirect?: boolean; [key: string]: unknown; } export interface AuthSession { user: User | null; isLoading: boolean; isAuthenticated: boolean; } export interface AuthContextType extends AuthSession { signIn: (provider?: string, options?: SignInOptions) => Promise; signOut: () => Promise; updateUser: (userData: Partial) => void; } export interface AuthProviderProps { children: ReactNode; // Adapter functions for different auth systems getSession?: () => Promise<{ user: User | null }>; signInAdapter?: (provider?: string, options?: SignInOptions) => Promise; signOutAdapter?: () => Promise; onAuthStateChange?: (user: User | null) => void; // Initial session data initialSession?: { user: User | null }; } const AuthContext = createContext(null); export { AuthContext }; export const AuthProvider: React.FC = ({ children, getSession, signInAdapter, signOutAdapter, onAuthStateChange, initialSession, }) => { const [user, setUser] = useState(initialSession?.user || null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const initializeAuth = async () => { if (getSession) { try { const session = await getSession(); setUser(session.user); onAuthStateChange?.(session.user); } catch (error) { console.error("Failed to get session:", error); setUser(null); onAuthStateChange?.(null); } } setIsLoading(false); }; initializeAuth(); }, [getSession, onAuthStateChange]); const signIn = async (provider?: string, options?: SignInOptions) => { if (signInAdapter) { setIsLoading(true); try { await signInAdapter(provider, options); // Refresh session after sign in if (getSession) { const session = await getSession(); setUser(session.user); onAuthStateChange?.(session.user); } } catch (error) { console.error("Sign in failed:", error); throw error; } finally { setIsLoading(false); } } else { throw new Error("Sign in adapter not provided"); } }; const signOut = async () => { if (signOutAdapter) { setIsLoading(true); try { await signOutAdapter(); setUser(null); onAuthStateChange?.(null); } catch (error) { console.error("Sign out failed:", error); throw error; } finally { setIsLoading(false); } } else { throw new Error("Sign out adapter not provided"); } }; const updateUser = (userData: Partial) => { if (user) { const updatedUser = { ...user, ...userData }; setUser(updatedUser); onAuthStateChange?.(updatedUser); } }; const value: AuthContextType = { user, isLoading, isAuthenticated: !!user, signIn, signOut, updateUser, }; return {children}; };