import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:travel_mate/services/error_service.dart'; import '../data/models/group.dart'; import '../data/models/group_member.dart'; class GroupRepository { final FirebaseFirestore _firestore = FirebaseFirestore.instance; final _errorService = ErrorService(); CollectionReference get _groupsCollection => _firestore.collection('groups'); CollectionReference _membersCollection(String groupId) { return _groupsCollection.doc(groupId).collection('members'); } Future createGroupWithMembers({ required Group group, required List members, }) async { try { return await _firestore.runTransaction((transaction) async { final groupRef = _groupsCollection.doc(); final groupData = group.toMap(); transaction.set(groupRef, groupData); for (var member in members) { final memberRef = groupRef.collection('members').doc(member.userId); transaction.set(memberRef, member.toMap()); } return groupRef.id; }); } catch (e) { throw Exception('Erreur lors de la création du groupe: $e'); } } Stream> getGroupsByUserId(String userId) { return _groupsCollection .snapshots() .asyncMap((snapshot) async { List userGroups = []; for (var groupDoc in snapshot.docs) { try { final groupId = groupDoc.id; // Vérifier si l'utilisateur est membre final memberDoc = await groupDoc.reference .collection('members') .doc(userId) .get(); if (memberDoc.exists) { final groupData = groupDoc.data() as Map; final group = Group.fromMap(groupData, groupId); final members = await getGroupMembers(groupId); userGroups.add(group.copyWith(members: members)); } else { _errorService.logInfo('group_repository.dart','Utilisateur NON membre de $groupId'); } } catch (e, stackTrace) { _errorService.logError(e.toString(), stackTrace); } } return userGroups; }) .distinct((prev, next) { // Comparer les listes pour éviter les doublons if (prev.length != next.length) { return false; } // Vérifier si les IDs sont identiques final prevIds = prev.map((g) => g.id).toSet(); final nextIds = next.map((g) => g.id).toSet(); final identical = prevIds.difference(nextIds).isEmpty && nextIds.difference(prevIds).isEmpty; return identical; }) .handleError((error, stackTrace) { _errorService.logError(error, stackTrace); return []; }); } Future getGroupById(String groupId) async { try { final doc = await _groupsCollection.doc(groupId).get(); if (!doc.exists) return null; final group = Group.fromMap(doc.data() as Map, doc.id); final members = await getGroupMembers(groupId); return group.copyWith(members: members); } catch (e) { throw Exception('Erreur lors de la récupération du groupe: $e'); } } Future getGroupByTripId(String tripId) async { try { final querySnapshot = await _groupsCollection .where('tripId', isEqualTo: tripId) .limit(1) .get(); if (querySnapshot.docs.isEmpty) return null; final doc = querySnapshot.docs.first; final group = Group.fromMap(doc.data() as Map, doc.id); final members = await getGroupMembers(doc.id); return group.copyWith(members: members); } catch (e) { throw Exception('Erreur lors de la récupération du groupe: $e'); } } Future> getGroupMembers(String groupId) async { try { final snapshot = await _membersCollection(groupId).get(); return snapshot.docs .map((doc) { return GroupMember.fromMap( doc.data() as Map, doc.id, ); }) .toList(); } catch (e) { throw Exception('Erreur lors de la récupération des membres: $e'); } } Future addMember(String groupId, GroupMember member) async { try { await _membersCollection(groupId).doc(member.userId).set(member.toMap()); await _groupsCollection.doc(groupId).update({ 'updatedAt': DateTime.now().millisecondsSinceEpoch, }); } catch (e) { throw Exception('Erreur lors de l\'ajout du membre: $e'); } } Future removeMember(String groupId, String userId) async { try { await _membersCollection(groupId).doc(userId).delete(); await _groupsCollection.doc(groupId).update({ 'updatedAt': DateTime.now().millisecondsSinceEpoch, }); } catch (e) { throw Exception('Erreur lors de la suppression du membre: $e'); } } Future updateGroup(String groupId, Group group) async { try { await _groupsCollection.doc(groupId).update( group.toMap()..['updatedAt'] = DateTime.now().millisecondsSinceEpoch, ); } catch (e) { throw Exception('Erreur lors de la mise à jour du groupe: $e'); } } Future deleteGroup(String tripId) async { try { final querySnapshot = await _groupsCollection .where('tripId', isEqualTo: tripId) .limit(1) .get(); if (querySnapshot.docs.isEmpty) { throw Exception('Aucun groupe trouvé pour ce voyage'); } final groupDoc = querySnapshot.docs.first; final groupId = groupDoc.id; final membersSnapshot = await _membersCollection(groupId).get(); for (var doc in membersSnapshot.docs) { await doc.reference.delete(); } await _groupsCollection.doc(groupId).delete(); } catch (e) { throw Exception('Erreur lors de la suppression du groupe: $e'); } } Stream> watchGroupMembers(String groupId) { return _membersCollection(groupId).snapshots().map( (snapshot) => snapshot.docs .map((doc) => GroupMember.fromMap( doc.data() as Map, doc.id, )) .toList(), ); } }