import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';
import 'user_balance.dart';
import 'settlement.dart';

class GroupBalance extends Equatable {
  final String groupId;
  final List<UserBalance> userBalances;
  final List<Settlement> settlements;
  final double totalExpenses;
  final DateTime calculatedAt;

  const GroupBalance({
    required this.groupId,
    required this.userBalances,
    required this.settlements,
    required this.totalExpenses,
    required this.calculatedAt,
  });

  // Constructeur factory pour créer depuis une Map
  factory GroupBalance.fromMap(Map<String, dynamic> map) {
    return GroupBalance(
      groupId: map['groupId'] ?? '',
      userBalances: (map['userBalances'] as List?)
          ?.map((userBalance) => UserBalance.fromMap(userBalance as Map<String, dynamic>))
          .toList() ?? [],
      settlements: (map['settlements'] as List?)
          ?.map((settlement) => Settlement.fromMap(settlement as Map<String, dynamic>))
          .toList() ?? [],
      totalExpenses: (map['totalExpenses'] as num?)?.toDouble() ?? 0.0,
      calculatedAt: _parseDateTime(map['calculatedAt']),
    );
  }

  // Convertir en Map pour Firestore
  Map<String, dynamic> toMap() {
    return {
      'groupId': groupId,
      'userBalances': userBalances.map((userBalance) => userBalance.toMap()).toList(),
      'settlements': settlements.map((settlement) => settlement.toMap()).toList(),
      'totalExpenses': totalExpenses,
      'calculatedAt': Timestamp.fromDate(calculatedAt),
    };
  }

  // Méthode copyWith pour créer une copie modifiée
  GroupBalance copyWith({
    String? groupId,
    List<UserBalance>? userBalances,
    List<Settlement>? settlements,
    double? totalExpenses,
    DateTime? calculatedAt,
  }) {
    return GroupBalance(
      groupId: groupId ?? this.groupId,
      userBalances: userBalances ?? this.userBalances,
      settlements: settlements ?? this.settlements,
      totalExpenses: totalExpenses ?? this.totalExpenses,
      calculatedAt: calculatedAt ?? this.calculatedAt,
    );
  }

  // Helper pour parser les dates de différents formats
  static DateTime _parseDateTime(dynamic value) {
    if (value is Timestamp) return value.toDate();
    if (value is String) return DateTime.parse(value);
    if (value is DateTime) return value;
    if (value is int) return DateTime.fromMillisecondsSinceEpoch(value);
    return DateTime.now();
  }

  // Méthodes utilitaires pour la logique métier
  bool get hasUnbalancedUsers => userBalances.any((balance) => !balance.isBalanced);
  
  bool get hasSettlements => settlements.isNotEmpty;
  
  double get totalSettlementAmount => settlements.fold(0.0, (sum, settlement) => sum + settlement.amount);
  
  List<UserBalance> get creditors => userBalances.where((b) => b.shouldReceive).toList();
  
  List<UserBalance> get debtors => userBalances.where((b) => b.shouldPay).toList();
  
  int get participantCount => userBalances.length;

  @override
  List<Object?> get props => [groupId, calculatedAt];

  @override
  String toString() {
    return 'GroupBalance(groupId: $groupId, totalExpenses: $totalExpenses, participantCount: $participantCount, calculatedAt: $calculatedAt)';
  }
}