import { AppState, type AppStateStatus } from 'react-native' import { create } from 'zustand' import { subscription } from '@/lib/auth' import type { ApiError } from '@/lib/types' interface UserBalanceState { balance: number loading: boolean error: ApiError | null lastLoadTime: number pollingEnabled: boolean } interface UserBalanceActions { load: (force?: boolean) => Promise setBalance: (balance: number) => void deductBalance: (amount: number) => void startPolling: () => void stopPolling: () => void restartPolling: () => void reset: () => void } type UserBalanceStore = UserBalanceState & UserBalanceActions const POLLING_INTERVAL = 60e3 // 60秒轮询一次 const DEBOUNCE_TIME = 5e3 // 5秒防抖 let pollingInterval: ReturnType | null = null let loadingPromise: Promise | null = null let appStateSubscription: { remove: () => void } | null = null export const useUserBalanceStore = create((set, get) => ({ // State balance: 0, loading: false, error: null, lastLoadTime: 0, pollingEnabled: false, // Actions load: async (force = false) => { const state = get() const now = Date.now() const timeSinceLastLoad = now - state.lastLoadTime // 如果不是强制刷新,且距离上次调用少于5秒,则跳过 if (!force && timeSinceLastLoad < DEBOUNCE_TIME) { console.log('跳过余额加载,距离上次调用时间过短:', timeSinceLastLoad + 'ms') return } // 如果已经在加载中且不是强制刷新,直接返回 if (state.loading && !force) { console.log('余额加载中,跳过重复请求') return loadingPromise || undefined } set({ lastLoadTime: now, loading: true }) loadingPromise = (async () => { try { const { data, error } = await subscription.list() if (error) { set({ error, loading: false }) return } const meteredSubscriptions = data?.filter((sub) => sub.type === 'metered') || [] const creditBalance = meteredSubscriptions[0]?.creditBalance?.remainingTokenBalance || 0 set({ balance: creditBalance, error: null, loading: false }) } catch (e) { console.error('加载余额失败:', e) set({ loading: false }) } finally { loadingPromise = null } })() return loadingPromise }, setBalance: (balance: number) => { set({ balance }) }, deductBalance: (amount: number) => { set((state) => ({ balance: Math.max(0, state.balance - amount) })) }, startPolling: () => { const { stopPolling, load } = get() // 先清理可能存在的旧轮询状态 stopPolling() console.log('开始余额轮询,间隔:', POLLING_INTERVAL / 1000, '秒') set({ pollingEnabled: true }) // 立即执行一次 load(false) // 设置定时器 pollingInterval = setInterval(() => { const state = get() if (state.pollingEnabled) { load(false) } }, POLLING_INTERVAL) // 设置应用状态监听 if (!appStateSubscription) { appStateSubscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => { const state = get() if (nextAppState === 'active' && state.pollingEnabled) { console.log('应用回到前台,重启余额轮询') get().restartPolling() } else if (nextAppState === 'background' || nextAppState === 'inactive') { console.log('应用进入后台,暂停余额轮询') get().stopPolling() } }) } }, stopPolling: () => { console.log('停止余额轮询') set({ pollingEnabled: false }) if (pollingInterval) { clearInterval(pollingInterval) pollingInterval = null } }, restartPolling: () => { const { stopPolling, startPolling } = get() stopPolling() setTimeout(() => startPolling(), 1000) // 延迟1秒重启 }, reset: () => { const { stopPolling } = get() stopPolling() set({ balance: 0, loading: false, error: null, lastLoadTime: 0, pollingEnabled: false, }) // 清理应用状态监听器 if (appStateSubscription) { appStateSubscription.remove() appStateSubscription = null } }, }))