import { useRouter } from "expo-router"; import React, { createContext, useContext, useEffect, useState } from "react"; import { deleteSetting, getSetting, initDB, salvarUsuario, setSetting, } from "@/services/db"; import { getUserIdFromToken } from "@/utils/jwt"; type User = { id: string; email: string; name: string; }; type AuthContextType = { user: User | null; token: string | null; isLoading: boolean; login: ( email: string, password: string, token: string, user: User, ) => Promise; signup: ( name: string, email: string, userId: string, token: string, ) => Promise; logout: () => Promise; isSignedIn: boolean; }; const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [token, setToken] = useState(null); const [isLoading, setIsLoading] = useState(true); const router = useRouter(); useEffect(() => { bootstrapAsync(); }, []); const bootstrapAsync = async () => { try { await initDB(); const storedToken = await getSetting("authToken"); const storedUser = await getSetting("user"); if (storedToken && storedUser) { let parsedUser: User = JSON.parse(storedUser); const realId = getUserIdFromToken(storedToken); if (realId && realId !== parsedUser.id) { await salvarUsuario({ id: realId, email: parsedUser.email, name: parsedUser.name, token: storedToken, }); parsedUser = { ...parsedUser, id: realId }; await setSetting("user", JSON.stringify(parsedUser)); } setToken(storedToken); setUser(parsedUser); router.replace("/home"); } else { setToken(null); setUser(null); router.replace("/"); } } catch (e) { console.error("Failed to restore token", e); } finally { setIsLoading(false); } }; const authContext: AuthContextType = { user, token, isLoading, isSignedIn: token !== null, login: async ( _email: string, _password: string, authToken: string, authUser: User, ) => { try { setToken(authToken); setUser(authUser); await setSetting("authToken", authToken); await setSetting("user", JSON.stringify(authUser)); router.replace("/home"); } catch (error) { console.error("Login failed:", error); throw error; } }, signup: async ( name: string, email: string, userId: string, authToken: string, ) => { try { const newUser: User = { id: userId, email, name, }; setToken(authToken); setUser(newUser); await setSetting("authToken", authToken); await setSetting("user", JSON.stringify(newUser)); router.replace("/home"); } catch (error) { console.error("Signup failed:", error); throw error; } }, logout: async () => { try { await deleteSetting("authToken"); await deleteSetting("user"); setToken(null); setUser(null); router.replace("/"); } catch (error) { console.error("Logout failed:", error); throw error; } }, }; return ( {children} ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error("useAuth must be used within an AuthProvider"); } return context; }