import { create } from 'zustand'; import { ApiError } from './api-client'; import { authApi, type UserProfile, type LoginPayload, type RegisterPayload } from './auth-api'; function hasAuthCookie(): boolean { if (typeof document === 'undefined') return false; return document.cookie.includes('goodgo_authenticated=1'); } interface AuthState { user: UserProfile | null; isAuthenticated: boolean; isLoading: boolean; error: string | null; login: (data: LoginPayload) => Promise; register: (data: RegisterPayload) => Promise; handleOAuthCallback: (accessToken: string, refreshToken: string, expiresIn?: number) => Promise; logout: () => Promise; refreshToken: () => Promise; fetchProfile: () => Promise; initialize: () => Promise; clearError: () => void; } export const useAuthStore = create((set, get) => ({ user: null, isAuthenticated: false, isLoading: false, error: null, login: async (data) => { set({ isLoading: true, error: null }); try { await authApi.login(data); set({ isAuthenticated: true, isLoading: false }); await get().fetchProfile(); } catch (e) { const message = e instanceof ApiError ? e.message : 'Đăng nhập thất bại'; set({ isLoading: false, error: message }); throw e; } }, register: async (data) => { set({ isLoading: true, error: null }); try { await authApi.register(data); set({ isAuthenticated: true, isLoading: false }); await get().fetchProfile(); } catch (e) { const message = e instanceof ApiError ? e.message : 'Đăng ký thất bại'; set({ isLoading: false, error: message }); throw e; } }, handleOAuthCallback: async (accessToken, refreshToken, expiresIn) => { set({ isLoading: true, error: null }); try { await authApi.exchangeToken(accessToken, refreshToken, expiresIn); set({ isAuthenticated: true, isLoading: false }); await get().fetchProfile(); } catch (e) { const message = e instanceof ApiError ? e.message : 'Đăng nhập OAuth thất bại'; set({ isLoading: false, error: message }); throw e; } }, logout: async () => { try { await authApi.logout(); } catch { // Clear state even if API call fails } set({ user: null, isAuthenticated: false, error: null }); }, refreshToken: async () => { try { await authApi.refresh(); set({ isAuthenticated: true }); return true; } catch { set({ user: null, isAuthenticated: false }); return false; } }, fetchProfile: async () => { try { const user = await authApi.getProfile(); set({ user, isAuthenticated: true }); } catch (e) { if (e instanceof ApiError && e.status === 401) { const refreshed = await get().refreshToken(); if (refreshed) { try { const user = await authApi.getProfile(); set({ user, isAuthenticated: true }); } catch { set({ user: null, isAuthenticated: false }); } } } } }, initialize: async () => { if (!hasAuthCookie()) return; set({ isAuthenticated: true }); await get().fetchProfile(); }, clearError: () => set({ error: null }), }));