import { createContext, useContext, useEffect, useState, type ReactNode } from "react"; import type { Session, User } from "@supabase/supabase-js"; import { supabase } from "@/integrations/supabase/client"; export type AppRole = "admin" | "attorney" | "paralegal" | "legal_clerk" | "staff"; interface AuthState { session: Session | null; user: User | null; roles: AppRole[]; loading: boolean; isAdmin: boolean; signIn: (email: string, password: string) => Promise<{ error: string | null }>; signOut: () => Promise; refreshRoles: () => Promise; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: ReactNode }) { const [session, setSession] = useState(null); const [user, setUser] = useState(null); const [roles, setRoles] = useState([]); const [loading, setLoading] = useState(true); const loadRoles = async (uid: string | undefined) => { if (!uid) { setRoles([]); return; } const { data } = await supabase.from("user_roles").select("role").eq("user_id", uid); setRoles((data ?? []).map((r) => r.role as AppRole)); }; useEffect(() => { const { data: sub } = supabase.auth.onAuthStateChange((_event, sess) => { setSession(sess); setUser(sess?.user ?? null); // Defer DB call to avoid deadlock setTimeout(() => { loadRoles(sess?.user?.id); }, 0); }); supabase.auth.getSession().then(({ data: { session: sess } }) => { setSession(sess); setUser(sess?.user ?? null); loadRoles(sess?.user?.id).finally(() => setLoading(false)); }); return () => sub.subscription.unsubscribe(); }, []); const signIn = async (email: string, password: string) => { const { error } = await supabase.auth.signInWithPassword({ email, password }); return { error: error?.message ?? null }; }; const signOut = async () => { await supabase.auth.signOut(); setRoles([]); }; const refreshRoles = async () => loadRoles(user?.id); return ( {children} ); } export function useAuth() { const ctx = useContext(AuthContext); if (!ctx) throw new Error("useAuth must be used within AuthProvider"); return ctx; }