import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react'; import { apiAuth } from '../api'; export interface StaffUser { id: number; email: string; fullName: string; mustChangePassword: boolean; } interface AuthState { token: string | null; staff: StaffUser | null; loading: boolean; login: (email: string, password: string) => Promise; provision: (email: string) => Promise; logout: () => void; changePassword: (oldPassword: string, newPassword: string) => Promise; forgotPassword: (email: string) => Promise; resetPassword: (token: string, newPassword: string) => Promise; refreshMe: () => Promise; } const TOKEN_KEY = 'sc_staff_token'; const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [token, setToken] = useState(() => localStorage.getItem(TOKEN_KEY)); const [staff, setStaff] = useState(null); const [loading, setLoading] = useState(true); const applySession = useCallback((nextToken: string | null, nextStaff: StaffUser | null) => { setToken(nextToken); setStaff(nextStaff); if (nextToken) { localStorage.setItem(TOKEN_KEY, nextToken); } else { localStorage.removeItem(TOKEN_KEY); } }, []); const refreshMe = useCallback(async () => { if (!token) { setStaff(null); setLoading(false); return; } try { const res = await apiAuth.me(); setStaff(res.staff); } catch { applySession(null, null); } finally { setLoading(false); } }, [token, applySession]); useEffect(() => { refreshMe(); }, [refreshMe]); const login = useCallback(async (email: string, password: string) => { const res = await apiAuth.login(email, password); applySession(res.token, res.staff); }, [applySession]); const provision = useCallback(async (email: string) => { const res = await apiAuth.provision(email); return res.message; }, []); const logout = useCallback(() => { applySession(null, null); }, [applySession]); const changePassword = useCallback(async (oldPassword: string, newPassword: string) => { const res = await apiAuth.changePassword(oldPassword, newPassword); applySession(res.token, res.staff); }, [applySession]); const forgotPassword = useCallback(async (email: string) => { const res = await apiAuth.forgotPassword(email); return res.message; }, []); const resetPassword = useCallback(async (resetToken: string, newPassword: string) => { await apiAuth.resetPassword(resetToken, newPassword); }, []); const value = useMemo(() => ({ token, staff, loading, login, provision, logout, changePassword, forgotPassword, resetPassword, refreshMe, }), [token, staff, loading, login, provision, logout, changePassword, forgotPassword, resetPassword, refreshMe]); return {children}; } export function useAuth() { const ctx = useContext(AuthContext); if (!ctx) throw new Error('useAuth must be used within AuthProvider'); return ctx; } export function getStoredToken(): string | null { return localStorage.getItem(TOKEN_KEY); }