import { useCallback, useEffect, useMemo, useRef } from 'react'; import { FirebaseAuthTypes } from '../firebase'; import { UserWallet, WalletService } from '../services/walletService'; import { useUserWalletStore } from '../stores/userWalletStore'; import type { WalletCacheEntry } from '../stores/userWalletStore'; import { useGlobalLoading } from './useGlobalLoading'; interface UseUserWalletReturn { wallet: UserWallet | null; loading: boolean; error: string | null; refreshWallet: () => Promise; balanceInDollars: number; // Helper to get balance in dollars formattedBalance: string; // Helper to get formatted balance addCreditCard: ( cardData: { cardNumber: string; expiryDate: string; cvv: string; } ) => Promise; removeCreditCard: (cardId: string) => Promise; } const defaultEntry: WalletCacheEntry = { wallet: null, loading: false, error: null, }; export const useUserWallet = (user: FirebaseAuthTypes.User | null): UseUserWalletReturn => { const uid = user?.uid ?? null; const lastUidRef = useRef(null); const ensureSubscription = useUserWalletStore((state) => state.ensureSubscription); const refreshFromStore = useUserWalletStore((state) => state.refreshWallet); const removeWallet = useUserWalletStore((state) => state.removeWallet); const setWalletState = useUserWalletStore((state) => state.setWalletState); const entry = useUserWalletStore( useCallback( (state) => (uid ? state.wallets[uid] ?? defaultEntry : defaultEntry), [uid] ) ); const { withLoading } = useGlobalLoading(); useEffect(() => { if (lastUidRef.current && lastUidRef.current !== uid) { removeWallet(lastUidRef.current); } lastUidRef.current = uid; }, [uid, removeWallet]); useEffect(() => { if (!uid) { return; } ensureSubscription(uid); }, [ensureSubscription, uid]); const refreshWallet = useCallback(async () => { if (!uid) { return; } await withLoading(() => refreshFromStore(uid)); }, [refreshFromStore, uid, withLoading]); const addCreditCard = useCallback(async ( cardData: { cardNumber: string; expiryDate: string; cvv: string; } ) => { if (!uid) { return; } setWalletState(uid, { loading: true, error: null }); try { const result = await withLoading(() => WalletService.addCreditCard(uid, cardData)); if (!result.success) { setWalletState(uid, { loading: false, error: result.error || 'Failed to add credit card', }); return; } setWalletState(uid, { loading: false, error: null }); } catch (err) { setWalletState(uid, { loading: false, error: err instanceof Error ? err.message : 'Failed to add credit card', }); } }, [setWalletState, uid, withLoading]); const removeCreditCard = useCallback(async (cardId: string) => { if (!uid) { return; } setWalletState(uid, { loading: true, error: null }); try { const result = await withLoading(() => WalletService.removeCreditCard(uid, cardId)); if (!result.success) { setWalletState(uid, { loading: false, error: result.error || 'Failed to remove credit card', }); return; } setWalletState(uid, { loading: false, error: null }); } catch (err) { setWalletState(uid, { loading: false, error: err instanceof Error ? err.message : 'Failed to remove credit card', }); } }, [setWalletState, uid, withLoading]); return useMemo(() => { const wallet = uid ? entry.wallet : null; const balanceInDollars = wallet ? wallet.balance / 100 : 0; const formattedBalance = wallet ? `${wallet.currency} ${(wallet.balance / 100).toFixed(2)}` : `USD 0.00`; return { wallet, loading: uid ? entry.loading : false, error: uid ? entry.error : null, refreshWallet, balanceInDollars, formattedBalance, addCreditCard, removeCreditCard, }; }, [addCreditCard, entry.error, entry.loading, entry.wallet, refreshWallet, removeCreditCard, uid]); }; // Standalone function to fetch any user's wallet (useful for admin features) export const fetchUserWallet = async (uid: string): Promise => { if (!uid) { return null; } const cached = useUserWalletStore.getState().wallets[uid]?.wallet; if (cached) { return cached; } try { return await useUserWalletStore.getState().refreshWallet(uid); } catch (error) { console.error('Error fetching user wallet:', error); const res = await WalletService.getUserWallet(uid); return res.wallet ?? null; } };