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<void>;
  balanceInDollars: number; // Helper to get balance in dollars
  formattedBalance: string; // Helper to get formatted balance
  addCreditCard: (
    cardData: {
      cardNumber: string;
      expiryDate: string;
      cvv: string;
    }
  ) => Promise<void>;
  removeCreditCard: (cardId: string) => Promise<void>;
}

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<string | null>(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<UserWallet | null> => {
  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;
  }
};
