import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:travel_mate/services/error_service.dart'; import '../blocs/user/user_state.dart'; class UserService { final _errorService = ErrorService(); final FirebaseFirestore _firestore; final FirebaseAuth _auth; static const String _usersCollection = 'users'; UserService({ FirebaseFirestore? firestore, FirebaseAuth? auth, }) : _firestore = firestore ?? FirebaseFirestore.instance, _auth = auth ?? FirebaseAuth.instance; // Obtenir l'utilisateur connecté actuel User? getCurrentFirebaseUser() { return _auth.currentUser; } // Obtenir l'ID de l'utilisateur connecté String? getCurrentUserId() { return _auth.currentUser?.uid; } // Créer un nouvel utilisateur dans Firestore Future createUser(UserModel user) async { try { await _firestore .collection(_usersCollection) .doc(user.id) .set(user.toJson()); return true; } catch (e) { _errorService.logError('Erreur lors de la création de l\'utilisateur: $e', StackTrace.current); return false; } } // Obtenir un utilisateur par son ID Future getUserById(String userId) async { try { final doc = await _firestore .collection(_usersCollection) .doc(userId) .get(); if (doc.exists) { return UserModel.fromJson({ 'id': doc.id, ...doc.data() as Map, }); } return null; } catch (e) { _errorService.logError('Erreur lors de la récupération de l\'utilisateur: $e', StackTrace.current); return null; } } // Obtenir un utilisateur par son email Future getUserByEmail(String email) async { try { final querySnapshot = await _firestore .collection(_usersCollection) .where('email', isEqualTo: email) .limit(1) .get(); if (querySnapshot.docs.isNotEmpty) { final doc = querySnapshot.docs.first; return UserModel.fromJson({ 'id': doc.id, ...doc.data(), }); } return null; } catch (e) { _errorService.logError('Erreur lors de la récupération de l\'utilisateur par email: $e', StackTrace.current); return null; } } // Obtenir l'ID d'un utilisateur par son email Future getUserIdByEmail(String email) async { try { final querySnapshot = await _firestore .collection(_usersCollection) .where('email', isEqualTo: email) .limit(1) .get(); if (querySnapshot.docs.isNotEmpty) { return querySnapshot.docs.first.id; } return null; } catch (e) { _errorService.logError('Erreur lors de la récupération de l\'ID utilisateur: $e', StackTrace.current); return null; } } // Mettre à jour un utilisateur Future updateUser(String userId, Map userData) async { try { await _firestore .collection(_usersCollection) .doc(userId) .update(userData); return true; } catch (e) { _errorService.logError('Erreur lors de la mise à jour de l\'utilisateur: $e', StackTrace.current); return false; } } // Supprimer un utilisateur Future deleteUser(String userId) async { try { await _firestore .collection(_usersCollection) .doc(userId) .delete(); return true; } catch (e) { _errorService.logError('Erreur lors de la suppression de l\'utilisateur: $e', StackTrace.current); return false; } } // Vérifier si un email existe déjà Future emailExists(String email) async { try { final querySnapshot = await _firestore .collection(_usersCollection) .where('email', isEqualTo: email) .limit(1) .get(); return querySnapshot.docs.isNotEmpty; } catch (e) { _errorService.logError('Erreur lors de la vérification de l\'email: $e', StackTrace.current); return false; } } // Obtenir plusieurs utilisateurs par leurs IDs Future> getUsersByIds(List userIds) async { try { if (userIds.isEmpty) return []; final List users = []; // Firestore a une limite de 10 éléments pour les requêtes 'in' // Donc on divise en chunks de 10 for (int i = 0; i < userIds.length; i += 10) { final chunk = userIds.skip(i).take(10).toList(); final querySnapshot = await _firestore .collection(_usersCollection) .where(FieldPath.documentId, whereIn: chunk) .get(); for (var doc in querySnapshot.docs) { users.add(UserModel.fromJson({ 'id': doc.id, ...doc.data(), })); } } return users; } catch (e) { _errorService.logError('Erreur lors de la récupération des utilisateurs: $e', StackTrace.current); return []; } } // Obtenir tous les utilisateurs (à utiliser avec précaution) Future> getAllUsers() async { try { final querySnapshot = await _firestore .collection(_usersCollection) .get(); return querySnapshot.docs.map((doc) { return UserModel.fromJson({ 'id': doc.id, ...doc.data(), }); }).toList(); } catch (e) { _errorService.logError('Erreur lors de la récupération de tous les utilisateurs: $e', StackTrace.current); return []; } } // Stream pour écouter les changements d'un utilisateur Stream getUserStream(String userId) { return _firestore .collection(_usersCollection) .doc(userId) .snapshots() .map((doc) { if (doc.exists) { return UserModel.fromJson({ 'id': doc.id, ...doc.data() as Map, }); } return null; }); } // Rechercher des utilisateurs par nom ou email Future> searchUsers(String query) async { try { if (query.isEmpty) return []; final queryLower = query.toLowerCase(); // Recherche par email final emailResults = await _firestore .collection(_usersCollection) .where('email', isGreaterThanOrEqualTo: queryLower) .where('email', isLessThanOrEqualTo: '$queryLower\uf8ff') .limit(10) .get(); // Recherche par prénom final prenomResults = await _firestore .collection(_usersCollection) .where('prenom', isGreaterThanOrEqualTo: queryLower) .where('prenom', isLessThanOrEqualTo: '$queryLower\uf8ff') .limit(10) .get(); // Combiner et dédupliquer les résultats final Map usersMap = {}; for (var doc in emailResults.docs) { usersMap[doc.id] = UserModel.fromJson({ 'id': doc.id, ...doc.data(), }); } for (var doc in prenomResults.docs) { usersMap[doc.id] = UserModel.fromJson({ 'id': doc.id, ...doc.data(), }); } return usersMap.values.toList(); } catch (e) { _errorService.logError('Erreur lors de la recherche d\'utilisateurs: $e', StackTrace.current); return []; } } // Mettre à jour la dernière connexion de l'utilisateur Future updateLastLogin(String userId) async { try { await _firestore .collection(_usersCollection) .doc(userId) .update({ 'lastLogin': FieldValue.serverTimestamp(), }); return true; } catch (e) { _errorService.logError('Erreur lors de la mise à jour de la dernière connexion: $e', StackTrace.current); return false; } } // Vérifier si l'utilisateur existe dans Firestore Future userExists(String userId) async { try { final doc = await _firestore .collection(_usersCollection) .doc(userId) .get(); return doc.exists; } catch (e) { _errorService.logError('Erreur lors de la vérification de l\'existence de l\'utilisateur: $e', StackTrace.current); return false; } } }