import { create } from 'zustand' import { loginApi, googleLoginApi, logoutApi, fetchMe, PendingApprovalError } from '../services/authApi' import type { AuthUser } from '../services/authApi' interface AuthState { user: AuthUser | null isAuthenticated: boolean isLoading: boolean error: string | null pendingMessage: string | null login: (account: string, password: string) => Promise googleLogin: (credential: string) => Promise logout: () => Promise checkSession: () => Promise hasPermission: (resource: string) => boolean clearError: () => void } export const useAuthStore = create((set, get) => ({ user: null, isAuthenticated: false, isLoading: true, error: null, pendingMessage: null, login: async (account: string, password: string) => { set({ isLoading: true, error: null }) try { const user = await loginApi(account, password) set({ user, isAuthenticated: true, isLoading: false }) } catch (err) { const message = (err as { message?: string })?.message || '로그인에 실패했습니다.' set({ isLoading: false, error: message }) throw err } }, googleLogin: async (credential: string) => { set({ isLoading: true, error: null, pendingMessage: null }) try { const user = await googleLoginApi(credential) set({ user, isAuthenticated: true, isLoading: false }) } catch (err) { if (err instanceof PendingApprovalError) { set({ isLoading: false, pendingMessage: err.message }) return } const message = (err as { message?: string })?.message || 'Google 로그인에 실패했습니다.' set({ isLoading: false, error: message }) throw err } }, logout: async () => { try { await logoutApi() } catch { // 로그아웃 실패해도 클라이언트 상태는 초기화 } set({ user: null, isAuthenticated: false, isLoading: false, error: null }) }, checkSession: async () => { set({ isLoading: true }) try { const user = await fetchMe() set({ user, isAuthenticated: true, isLoading: false }) } catch { set({ user: null, isAuthenticated: false, isLoading: false }) } }, hasPermission: (resource: string) => { const { user } = get() if (!user) return false return user.permissions.includes(resource) }, clearError: () => set({ error: null, pendingMessage: null }), }))