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, operation?: 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, operation?: string) => { const { user } = get() if (!user) return false const op = operation ?? 'READ' // 정확한 리소스 권한 확인 const ops = user.permissions[resource] if (ops) return ops.includes(op) // 'scat:survey' → 부모 'scat' 권한으로 fallback const colonIdx = resource.indexOf(':') if (colonIdx > 0) { const parent = resource.substring(0, colonIdx) const parentOps = user.permissions[parent] if (parentOps) return parentOps.includes(op) } return false }, clearError: () => set({ error: null, pendingMessage: null }), }))