import React, { createContext, useContext, useMemo, useState } from "react"; import { API_URL } from "./api"; const AuthCtx = createContext(null); function loadStorage() { try { return JSON.parse(localStorage.getItem("nexapg_auth") || "null"); } catch { return null; } } export function AuthProvider({ children }) { const initial = loadStorage(); const [tokens, setTokens] = useState(initial?.tokens || null); const [me, setMe] = useState(initial?.me || null); const persist = (nextTokens, nextMe) => { if (nextTokens && nextMe) { localStorage.setItem("nexapg_auth", JSON.stringify({ tokens: nextTokens, me: nextMe })); } else { localStorage.removeItem("nexapg_auth"); } }; const refresh = async () => { if (!tokens?.refreshToken) return null; const res = await fetch(`${API_URL}/auth/refresh`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ refresh_token: tokens.refreshToken }), }); if (!res.ok) { setTokens(null); setMe(null); persist(null, null); return null; } const data = await res.json(); const nextTokens = { accessToken: data.access_token, refreshToken: data.refresh_token }; setTokens(nextTokens); persist(nextTokens, me); return nextTokens; }; const login = async (email, password) => { const res = await fetch(`${API_URL}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); if (!res.ok) throw new Error("Login failed"); const data = await res.json(); const nextTokens = { accessToken: data.access_token, refreshToken: data.refresh_token }; const meRes = await fetch(`${API_URL}/me`, { headers: { Authorization: `Bearer ${nextTokens.accessToken}` }, }); if (!meRes.ok) throw new Error("Could not load user profile"); const profile = await meRes.json(); setTokens(nextTokens); setMe(profile); persist(nextTokens, profile); }; const logout = async () => { try { if (tokens?.accessToken) { await fetch(`${API_URL}/auth/logout`, { method: "POST", headers: { Authorization: `Bearer ${tokens.accessToken}` }, }); } } finally { setTokens(null); setMe(null); persist(null, null); } }; const value = useMemo(() => ({ tokens, me, login, logout, refresh }), [tokens, me]); return {children}; } export function useAuth() { const ctx = useContext(AuthCtx); if (!ctx) throw new Error("useAuth must be used inside AuthProvider"); return ctx; }