/**
 * Hook React pour la gestion du portefeuille électronique
 */

import { useState, useEffect, useCallback } from 'react';
import { useAuth } from '@/contexts/AuthContext';
import { WalletService, WalletBalance, Transaction, PaymentMethod, TransactionType, TransactionStatus } from '@/services/walletService';

export interface UseWalletOptions {
  autoRefresh?: boolean;
  refreshInterval?: number;
}

export function useWallet(options: UseWalletOptions = {}) {
  const { user } = useAuth();
  const { autoRefresh = true, refreshInterval = 30000 } = options;

  const [walletService] = useState(() => new WalletService());
  const [balance, setBalance] = useState<WalletBalance | null>(null);
  const [transactions, setTransactions] = useState<Transaction[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [refreshing, setRefreshing] = useState(false);

  // Charger les données du portefeuille
  const loadWalletData = useCallback(async (showLoading = true) => {
    if (!user?.id) return;

    try {
      if (showLoading) {
        setLoading(true);
      } else {
        setRefreshing(true);
      }
      setError(null);

      // Charger en parallèle le solde et les transactions
      const [balanceData, transactionsData] = await Promise.all([
        walletService.getBalance(user.id),
        walletService.getTransactions(user.id, { limit: 50 })
      ]);

      setBalance(balanceData);
      setTransactions(transactionsData);

    } catch (err) {
      console.error('Error loading wallet data:', err);
      setError(err instanceof Error ? err.message : 'Erreur lors du chargement du portefeuille');
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }, [user?.id, walletService]);

  // Rafraîchir uniquement le solde (plus léger)
  const refreshBalance = useCallback(async () => {
    if (!user?.id) return;

    try {
      const balanceData = await walletService.getBalance(user.id);
      setBalance(balanceData);
    } catch (err) {
      console.error('Error refreshing balance:', err);
    }
  }, [user?.id, walletService]);

  // Recharger le portefeuille
  const topUp = useCallback(async (
    amount: number,
    paymentMethod: PaymentMethod,
    metadata?: Record<string, any>
  ) => {
    if (!user?.id) {
      throw new Error('Utilisateur non connecté');
    }

    setError(null);
    
    try {
      const result = await walletService.topUp(user.id, amount, paymentMethod, metadata);
      
      if (result.success) {
        // Rafraîchir les données après succès
        await loadWalletData(false);
        return result.transactionId;
      } else {
        throw new Error(result.error || 'Erreur lors de la recharge');
      }
    } catch (err) {
      const error = err instanceof Error ? err.message : 'Erreur lors de la recharge';
      setError(error);
      throw new Error(error);
    }
  }, [user?.id, walletService, loadWalletData]);

  // Effectuer un paiement
  const makePayment = useCallback(async (
    amount: number,
    orderId: string,
    description: string,
    metadata?: any
  ) => {
    if (!user?.id) {
      throw new Error('Utilisateur non connecté');
    }

    setError(null);

    try {
      const result = await walletService.makePayment(user.id, amount, orderId, description, metadata);
      
      if (result.success) {
        await loadWalletData(false);
        return result.transactionId;
      } else {
        const error = result.insufficientFunds 
          ? 'Solde insuffisant. Rechargez votre portefeuille.'
          : result.error || 'Erreur lors du paiement';
        throw new Error(error);
      }
    } catch (err) {
      const error = err instanceof Error ? err.message : 'Erreur lors du paiement';
      setError(error);
      throw new Error(error);
    }
  }, [user?.id, walletService, loadWalletData]);

  // Effectuer un retrait
  const withdraw = useCallback(async (
    amount: number,
    paymentMethod: PaymentMethod,
    metadata?: Record<string, any>
  ) => {
    if (!user?.id) {
      throw new Error('Utilisateur non connecté');
    }

    setError(null);

    try {
      const result = await walletService.withdraw(user.id, amount, paymentMethod, metadata);
      
      if (result.success) {
        await loadWalletData(false);
        return result.transactionId;
      } else {
        throw new Error(result.error || 'Erreur lors du retrait');
      }
    } catch (err) {
      const error = err instanceof Error ? err.message : 'Erreur lors du retrait';
      setError(error);
      throw new Error(error);
    }
  }, [user?.id, walletService, loadWalletData]);

  // Filtrer les transactions
  const getFilteredTransactions = useCallback((
    type?: TransactionType,
    status?: TransactionStatus,
    limit?: number
  ) => {
    let filtered = transactions;

    if (type) {
      filtered = filtered.filter(tx => tx.type === type);
    }

    if (status) {
      filtered = filtered.filter(tx => tx.status === status);
    }

    if (limit) {
      filtered = filtered.slice(0, limit);
    }

    return filtered;
  }, [transactions]);

  // Charger plus de transactions
  const loadMoreTransactions = useCallback(async () => {
    if (!user?.id) return;

    try {
      const moreTransactions = await walletService.getTransactions(user.id, {
        offset: transactions.length,
        limit: 20
      });

      setTransactions(prev => [...prev, ...moreTransactions]);
    } catch (err) {
      console.error('Error loading more transactions:', err);
    }
  }, [user?.id, transactions.length, walletService]);

  // Obtenir les statistiques
  const getStats = useCallback(async (period: 'week' | 'month' | 'year' = 'month') => {
    if (!user?.id) return null;

    try {
      return await walletService.getWalletStats(user.id, period);
    } catch (err) {
      console.error('Error loading wallet stats:', err);
      return null;
    }
  }, [user?.id, walletService]);

  // Validation des montants
  const validateAmount = useCallback((amount: number, min?: number, max?: number) => {
    return walletService.validateAmount(amount, min, max);
  }, [walletService]);

  // Validation numéro de téléphone
  const validatePhoneNumber = useCallback((phone: string) => {
    return walletService.validatePhoneNumber(phone);
  }, [walletService]);

  // Formatage des montants
  const formatAmount = useCallback((amount: number, currency?: string) => {
    return walletService.formatAmount(amount, currency);
  }, [walletService]);

  // Auto-refresh
  useEffect(() => {
    if (!autoRefresh || !user?.id) return;

    const interval = setInterval(() => {
      refreshBalance();
    }, refreshInterval);

    return () => clearInterval(interval);
  }, [autoRefresh, refreshInterval, user?.id, refreshBalance]);

  // Chargement initial
  useEffect(() => {
    if (user?.id) {
      loadWalletData();
    }
  }, [user?.id, loadWalletData]);

  // Calculer des métriques utiles
  const metrics = {
    hasSufficientBalance: (amount: number) => balance && balance.available >= amount,
    totalTransactions: transactions.length,
    pendingTransactions: transactions.filter(tx => tx.status === TransactionStatus.PENDING).length,
    recentEarnings: transactions
      .filter(tx => 
        tx.type === TransactionType.EARNING && 
        new Date(tx.createdAt) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
      )
      .reduce((sum, tx) => sum + tx.amount, 0),
    recentSpending: Math.abs(transactions
      .filter(tx => 
        tx.type === TransactionType.PAYMENT && 
        new Date(tx.createdAt) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
      )
      .reduce((sum, tx) => sum + tx.amount, 0))
  };

  return {
    // État
    balance,
    transactions,
    loading,
    error,
    refreshing,

    // Actions
    topUp,
    makePayment,
    withdraw,
    refreshBalance,
    loadWalletData,
    loadMoreTransactions,

    // Utilitaires
    getFilteredTransactions,
    getStats,
    validateAmount,
    validatePhoneNumber,
    formatAmount,
    clearError: () => setError(null),

    // Métriques
    metrics,

    // Options de service
    topUpOptions: walletService.getTopUpOptions(),
    paymentMethods: walletService.getAvailablePaymentMethods(),

    // État dérivé
    hasBalance: balance && balance.available > 0,
    canMakePayment: (amount: number) => balance && balance.available >= amount,
    isConnected: !!user?.id
  };
}