/**
 * Service de portefeuille électronique pour MediFlash SOS+
 * Gère les transactions, dépôts, paiements et historique financier
 */

export interface WalletBalance {
  userId: string;
  balance: number; // En FCFA
  currency: 'FCFA' | 'EUR' | 'USD';
  lastUpdated: Date;
  frozen?: number; // Montant gelé pour transactions en cours
  available: number; // Solde disponible = balance - frozen
}

export interface Transaction {
  id: string;
  userId: string;
  type: TransactionType;
  amount: number;
  currency: string;
  status: TransactionStatus;
  description: string;
  metadata?: TransactionMetadata;
  createdAt: Date;
  processedAt?: Date;
  reference?: string; // Référence externe (Mobile Money, etc.)
  fee?: number; // Frais de transaction
  orderId?: string; // Commande associée
}

export enum TransactionType {
  DEPOSIT = 'deposit',           // Dépôt d'argent
  WITHDRAWAL = 'withdrawal',     // Retrait
  PAYMENT = 'payment',          // Paiement pour une commande
  REFUND = 'refund',            // Remboursement
  EARNING = 'earning',          // Gain (pharmacie/livreur)
  FEE = 'fee',                  // Frais de service
  BONUS = 'bonus',              // Bonus/récompense
  PENALTY = 'penalty',          // Pénalité
  TRANSFER = 'transfer'         // Transfert entre utilisateurs
}

export enum TransactionStatus {
  PENDING = 'pending',
  PROCESSING = 'processing',
  COMPLETED = 'completed',
  FAILED = 'failed',
  CANCELLED = 'cancelled',
  REFUNDED = 'refunded'
}

export interface TransactionMetadata {
  paymentMethod?: PaymentMethod;
  recipientId?: string;
  orderId?: string;
  pharmacyId?: string;
  courierId?: string;
  mobileMoneyNumber?: string;
  bankAccount?: string;
  feeBreakdown?: FeeBreakdown;
  exchangeRate?: number;
}

export interface PaymentMethod {
  id: string;
  type: 'mobile_money' | 'bank_transfer' | 'wallet' | 'cash' | 'card';
  provider?: string; // Orange Money, MTN Mobile Money, etc.
  identifier: string; // Numéro de téléphone, IBAN, etc.
  name: string; // Nom affiché
  isDefault?: boolean;
  metadata?: Record<string, any>;
}

export interface FeeBreakdown {
  serviceFee: number;
  processingFee: number;
  mobileFee?: number;
  totalFee: number;
}

export interface TopUpOption {
  amount: number;
  bonus?: number; // Bonus offert
  currency: string;
  paymentMethods: PaymentMethod[];
  description: string;
}

export interface WithdrawalLimits {
  daily: number;
  monthly: number;
  minimum: number;
  maximum: number;
}

export class WalletService {
  private apiClient: any;
  private currency = 'FCFA';

  constructor() {
    this.apiClient = {
      // Simulation d'un client API
      get: async (url: string) => this.simulateApiCall('GET', url),
      post: async (url: string, data: any) => this.simulateApiCall('POST', url, data),
      put: async (url: string, data: any) => this.simulateApiCall('PUT', url, data)
    };
  }

  // Simulation API (à remplacer par vrai client)
  private async simulateApiCall(method: string, url: string, data?: any) {
    console.log(`${method} ${url}`, data);
    
    // Simulation de délai réseau
    await new Promise(resolve => setTimeout(resolve, 500));
    
    // Simuler des réponses selon l'endpoint
    if (url.includes('/balance')) {
      return {
        success: true,
        data: {
          balance: 50000,
          frozen: 2500,
          available: 47500,
          currency: 'FCFA',
          lastUpdated: new Date()
        }
      };
    }
    
    if (url.includes('/transactions')) {
      return {
        success: true,
        data: [
          {
            id: 'tx_001',
            type: 'payment',
            amount: -2500,
            description: 'Paiement commande médicament urgence',
            createdAt: new Date(),
            status: 'completed'
          }
        ]
      };
    }

    return { success: true, data: data || {} };
  }

  /**
   * Récupérer le solde du portefeuille
   */
  async getBalance(userId: string): Promise<WalletBalance | null> {
    try {
      const response = await this.apiClient.get(`/api/wallet/${userId}/balance`);
      
      if (response.success) {
        return {
          userId,
          balance: response.data.balance,
          currency: response.data.currency || this.currency,
          lastUpdated: new Date(response.data.lastUpdated),
          frozen: response.data.frozen || 0,
          available: response.data.available || response.data.balance
        };
      }
      
      return null;
    } catch (error) {
      console.error('Error fetching wallet balance:', error);
      return null;
    }
  }

  /**
   * Historique des transactions
   */
  async getTransactions(
    userId: string,
    options: {
      limit?: number;
      offset?: number;
      type?: TransactionType;
      status?: TransactionStatus;
      startDate?: Date;
      endDate?: Date;
    } = {}
  ): Promise<Transaction[]> {
    try {
      const params = new URLSearchParams();
      if (options.limit) params.append('limit', options.limit.toString());
      if (options.offset) params.append('offset', options.offset.toString());
      if (options.type) params.append('type', options.type);
      if (options.status) params.append('status', options.status);
      if (options.startDate) params.append('start_date', options.startDate.toISOString());
      if (options.endDate) params.append('end_date', options.endDate.toISOString());

      const response = await this.apiClient.get(
        `/api/wallet/${userId}/transactions?${params.toString()}`
      );

      if (response.success) {
        return response.data.map((tx: any) => ({
          ...tx,
          createdAt: new Date(tx.createdAt),
          processedAt: tx.processedAt ? new Date(tx.processedAt) : undefined
        }));
      }

      return [];
    } catch (error) {
      console.error('Error fetching transactions:', error);
      return [];
    }
  }

  /**
   * Recharger le portefeuille
   */
  async topUp(
    userId: string,
    amount: number,
    paymentMethod: PaymentMethod,
    metadata?: Record<string, any>
  ): Promise<{ success: boolean; transactionId?: string; error?: string }> {
    try {
      // Validation
      if (amount <= 0) {
        return { success: false, error: 'Montant invalide' };
      }

      // Calculer les frais
      const fees = this.calculateTopUpFees(amount, paymentMethod.type);

      const response = await this.apiClient.post(`/api/wallet/${userId}/topup`, {
        amount,
        paymentMethod,
        fees,
        metadata: {
          ...metadata,
          clientIp: this.getClientIP(),
          userAgent: navigator.userAgent
        }
      });

      if (response.success) {
        return {
          success: true,
          transactionId: response.data.transactionId
        };
      }

      return {
        success: false,
        error: response.error || 'Erreur lors de la recharge'
      };
    } catch (error) {
      console.error('Error topping up wallet:', error);
      return {
        success: false,
        error: 'Erreur technique lors de la recharge'
      };
    }
  }

  /**
   * Effectuer un paiement
   */
  async makePayment(
    userId: string,
    amount: number,
    orderId: string,
    description: string,
    metadata?: TransactionMetadata
  ): Promise<{ success: boolean; transactionId?: string; error?: string; insufficientFunds?: boolean }> {
    try {
      // Vérifier le solde disponible
      const balance = await this.getBalance(userId);
      if (!balance || balance.available < amount) {
        return {
          success: false,
          error: 'Solde insuffisant',
          insufficientFunds: true
        };
      }

      const response = await this.apiClient.post(`/api/wallet/${userId}/payment`, {
        amount,
        orderId,
        description,
        metadata
      });

      if (response.success) {
        return {
          success: true,
          transactionId: response.data.transactionId
        };
      }

      return {
        success: false,
        error: response.error || 'Erreur lors du paiement'
      };
    } catch (error) {
      console.error('Error making payment:', error);
      return {
        success: false,
        error: 'Erreur technique lors du paiement'
      };
    }
  }

  /**
   * Effectuer un retrait
   */
  async withdraw(
    userId: string,
    amount: number,
    paymentMethod: PaymentMethod,
    metadata?: Record<string, any>
  ): Promise<{ success: boolean; transactionId?: string; error?: string }> {
    try {
      // Vérifier les limites de retrait
      const limits = await this.getWithdrawalLimits(userId);
      if (amount < limits.minimum || amount > limits.maximum) {
        return {
          success: false,
          error: `Montant doit être entre ${limits.minimum} et ${limits.maximum} ${this.currency}`
        };
      }

      // Vérifier le solde
      const balance = await this.getBalance(userId);
      if (!balance || balance.available < amount) {
        return {
          success: false,
          error: 'Solde insuffisant'
        };
      }

      const fees = this.calculateWithdrawalFees(amount, paymentMethod.type);
      const totalAmount = amount + fees.totalFee;

      if (balance.available < totalAmount) {
        return {
          success: false,
          error: `Solde insuffisant (frais inclus: ${fees.totalFee} ${this.currency})`
        };
      }

      const response = await this.apiClient.post(`/api/wallet/${userId}/withdrawal`, {
        amount,
        paymentMethod,
        fees,
        metadata
      });

      if (response.success) {
        return {
          success: true,
          transactionId: response.data.transactionId
        };
      }

      return {
        success: false,
        error: response.error || 'Erreur lors du retrait'
      };
    } catch (error) {
      console.error('Error withdrawing from wallet:', error);
      return {
        success: false,
        error: 'Erreur technique lors du retrait'
      };
    }
  }

  /**
   * Crédit pour pharmacies et livreurs
   */
  async creditEarnings(
    userId: string,
    amount: number,
    orderId: string,
    type: 'pharmacy_earning' | 'courier_earning',
    metadata?: TransactionMetadata
  ): Promise<{ success: boolean; transactionId?: string; error?: string }> {
    try {
      const response = await this.apiClient.post(`/api/wallet/${userId}/credit`, {
        amount,
        orderId,
        type,
        description: type === 'pharmacy_earning' 
          ? 'Paiement vente médicament'
          : 'Paiement livraison',
        metadata
      });

      if (response.success) {
        return {
          success: true,
          transactionId: response.data.transactionId
        };
      }

      return {
        success: false,
        error: response.error || 'Erreur lors du crédit'
      };
    } catch (error) {
      console.error('Error crediting earnings:', error);
      return {
        success: false,
        error: 'Erreur technique lors du crédit'
      };
    }
  }

  /**
   * Options de recharge disponibles
   */
  getTopUpOptions(): TopUpOption[] {
    return [
      {
        amount: 5000,
        currency: this.currency,
        paymentMethods: this.getAvailablePaymentMethods(),
        description: 'Recharge de base'
      },
      {
        amount: 10000,
        bonus: 500,
        currency: this.currency,
        paymentMethods: this.getAvailablePaymentMethods(),
        description: 'Recharge populaire + 500 FCFA bonus'
      },
      {
        amount: 25000,
        bonus: 2000,
        currency: this.currency,
        paymentMethods: this.getAvailablePaymentMethods(),
        description: 'Recharge premium + 2000 FCFA bonus'
      },
      {
        amount: 50000,
        bonus: 5000,
        currency: this.currency,
        paymentMethods: this.getAvailablePaymentMethods(),
        description: 'Recharge VIP + 5000 FCFA bonus'
      }
    ];
  }

  /**
   * Méthodes de paiement disponibles
   */
  getAvailablePaymentMethods(): PaymentMethod[] {
    return [
      {
        id: 'orange_money',
        type: 'mobile_money',
        provider: 'Orange Money',
        identifier: '',
        name: 'Orange Money'
      },
      {
        id: 'mtn_mobile_money',
        type: 'mobile_money',
        provider: 'MTN Mobile Money',
        identifier: '',
        name: 'MTN Mobile Money'
      },
      {
        id: 'moov_money',
        type: 'mobile_money',
        provider: 'Moov Money',
        identifier: '',
        name: 'Moov Money'
      },
      {
        id: 'bank_transfer',
        type: 'bank_transfer',
        provider: 'Virement Bancaire',
        identifier: '',
        name: 'Virement Bancaire'
      }
    ];
  }

  /**
   * Limites de retrait
   */
  async getWithdrawalLimits(userId: string): Promise<WithdrawalLimits> {
    // En production, récupérer depuis l'API selon le niveau de vérification
    return {
      daily: 200000,    // 200,000 FCFA par jour
      monthly: 2000000, // 2,000,000 FCFA par mois
      minimum: 1000,    // 1,000 FCFA minimum
      maximum: 50000    // 50,000 FCFA maximum par transaction
    };
  }

  /**
   * Calculer les frais de recharge
   */
  private calculateTopUpFees(amount: number, paymentType: string): FeeBreakdown {
    let processingFee = 0;
    let mobileFee = 0;

    switch (paymentType) {
      case 'mobile_money':
        // Frais Mobile Money: 1% du montant, minimum 100 FCFA
        mobileFee = Math.max(amount * 0.01, 100);
        processingFee = 50; // Frais de traitement fixe
        break;
      
      case 'bank_transfer':
        processingFee = 200; // Frais bancaires
        break;
      
      case 'card':
        processingFee = amount * 0.025; // 2.5% pour les cartes
        break;
      
      default:
        processingFee = 0;
    }

    return {
      serviceFee: 0, // Pas de frais service pour les recharges
      processingFee,
      mobileFee,
      totalFee: processingFee + mobileFee
    };
  }

  /**
   * Calculer les frais de retrait
   */
  private calculateWithdrawalFees(amount: number, paymentType: string): FeeBreakdown {
    let processingFee = 0;
    let mobileFee = 0;
    const serviceFee = amount * 0.005; // 0.5% de frais de service

    switch (paymentType) {
      case 'mobile_money':
        mobileFee = Math.max(amount * 0.015, 150); // 1.5% minimum 150 FCFA
        processingFee = 100;
        break;
      
      case 'bank_transfer':
        processingFee = 500; // Frais virement bancaire
        break;
      
      default:
        processingFee = 100;
    }

    return {
      serviceFee,
      processingFee,
      mobileFee,
      totalFee: serviceFee + processingFee + mobileFee
    };
  }

  /**
   * Statistiques du portefeuille
   */
  async getWalletStats(userId: string, period: 'week' | 'month' | 'year' = 'month') {
    try {
      const endDate = new Date();
      const startDate = new Date();
      
      switch (period) {
        case 'week':
          startDate.setDate(endDate.getDate() - 7);
          break;
        case 'month':
          startDate.setMonth(endDate.getMonth() - 1);
          break;
        case 'year':
          startDate.setFullYear(endDate.getFullYear() - 1);
          break;
      }

      const transactions = await this.getTransactions(userId, {
        startDate,
        endDate,
        limit: 1000
      });

      const stats = {
        totalDeposits: 0,
        totalWithdrawals: 0,
        totalPayments: 0,
        totalEarnings: 0,
        transactionCount: transactions.length,
        averageTransaction: 0,
        period
      };

      transactions.forEach(tx => {
        switch (tx.type) {
          case TransactionType.DEPOSIT:
            stats.totalDeposits += tx.amount;
            break;
          case TransactionType.WITHDRAWAL:
            stats.totalWithdrawals += Math.abs(tx.amount);
            break;
          case TransactionType.PAYMENT:
            stats.totalPayments += Math.abs(tx.amount);
            break;
          case TransactionType.EARNING:
            stats.totalEarnings += tx.amount;
            break;
        }
      });

      if (stats.transactionCount > 0) {
        const totalAmount = transactions.reduce((sum, tx) => sum + Math.abs(tx.amount), 0);
        stats.averageTransaction = totalAmount / stats.transactionCount;
      }

      return stats;
    } catch (error) {
      console.error('Error calculating wallet stats:', error);
      return null;
    }
  }

  /**
   * Utilitaires
   */
  private getClientIP(): string {
    // En production, obtenir l'IP réelle du client
    return '192.168.1.1';
  }

  formatAmount(amount: number, currency = this.currency): string {
    return new Intl.NumberFormat('fr-FR', {
      style: 'currency',
      currency: currency === 'FCFA' ? 'XOF' : currency,
      minimumFractionDigits: 0
    }).format(amount);
  }

  /**
   * Validation
   */
  validateAmount(amount: number, min = 100, max = 1000000): { valid: boolean; error?: string } {
    if (amount < min) {
      return { valid: false, error: `Montant minimum: ${min} ${this.currency}` };
    }
    if (amount > max) {
      return { valid: false, error: `Montant maximum: ${max} ${this.currency}` };
    }
    return { valid: true };
  }

  validatePhoneNumber(phone: string): { valid: boolean; error?: string } {
    // Validation numéro de téléphone pour Mobile Money
    const phoneRegex = /^(77|78|70|76|75|74|79)\d{7}$/;
    if (!phoneRegex.test(phone)) {
      return {
        valid: false,
        error: 'Numéro de téléphone invalide (format: 7XXXXXXXX)'
      };
    }
    return { valid: true };
  }
}