import { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react' import type { User, Session, AuthError } from '@supabase/supabase-js' import { supabase } from '../lib/supabase' import { api } from '../api/client' interface UserProfile { id: string email: string displayName: string | null isAdmin: boolean } interface AuthState { user: User | null session: Session | null loading: boolean isAdmin: boolean } interface AuthContextValue extends AuthState { signInWithEmail: (email: string, password: string) => Promise<{ error: AuthError | null }> signUpWithEmail: (email: string, password: string) => Promise<{ error: AuthError | null }> signInWithGoogle: () => Promise<{ error: AuthError | null }> signInWithDiscord: () => Promise<{ error: AuthError | null }> signOut: () => Promise } const AuthContext = createContext(null) async function syncUserProfile(session: Session | null): Promise { if (!session) return false try { const profile = await api.post('/users/me', {}) return profile.isAdmin } catch { return false } } export function AuthProvider({ children }: { children: React.ReactNode }) { const [state, setState] = useState({ user: null, session: null, loading: true, isAdmin: false, }) useEffect(() => { supabase.auth.getSession().then(async ({ data: { session } }) => { const isAdmin = await syncUserProfile(session) setState({ user: session?.user ?? null, session, loading: false, isAdmin }) }) const { data: { subscription }, } = supabase.auth.onAuthStateChange(async (_event, session) => { const isAdmin = await syncUserProfile(session) setState({ user: session?.user ?? null, session, loading: false, isAdmin }) }) return () => subscription.unsubscribe() }, []) const signInWithEmail = useCallback(async (email: string, password: string) => { const { error } = await supabase.auth.signInWithPassword({ email, password }) return { error } }, []) const signUpWithEmail = useCallback(async (email: string, password: string) => { const { error } = await supabase.auth.signUp({ email, password }) return { error } }, []) const signInWithGoogle = useCallback(async () => { const { error } = await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: `${window.location.origin}/auth/callback` }, }) return { error } }, []) const signInWithDiscord = useCallback(async () => { const { error } = await supabase.auth.signInWithOAuth({ provider: 'discord', options: { redirectTo: `${window.location.origin}/auth/callback` }, }) return { error } }, []) const signOut = useCallback(async () => { await supabase.auth.signOut() }, []) const value = useMemo( () => ({ ...state, signInWithEmail, signUpWithEmail, signInWithGoogle, signInWithDiscord, signOut, }), [state, signInWithEmail, signUpWithEmail, signInWithGoogle, signInWithDiscord, signOut] ) return {children} } export function useAuth() { const context = useContext(AuthContext) if (!context) { throw new Error('useAuth must be used within an AuthProvider') } return context }