import 'package:dartz/dartz.dart'; import '../../core/constants/env_config.dart'; import '../../core/errors/exceptions.dart'; import '../../core/errors/failures.dart'; import '../../core/utils/app_logger.dart'; import '../../domain/entities/user.dart'; import '../../domain/repositories/user_repository.dart'; import '../datasources/user_remote_data_source.dart'; import '../models/user_model.dart'; /// Implémentation du repository des utilisateurs. /// /// Cette classe fait le lien entre la couche domaine et la couche données, /// en convertissant les exceptions en failures et en gérant la transformation /// entre les modèles de données et les entités de domaine. /// /// **Usage:** /// ```dart /// final repository = UserRepositoryImpl( /// remoteDataSource: userRemoteDataSource, /// ); /// final result = await repository.getUser('user123'); /// result.fold( /// (failure) => print('Erreur: $failure'), /// (user) => print('Utilisateur: $user'), /// ); /// ``` class UserRepositoryImpl implements UserRepository { /// Crée une nouvelle instance de [UserRepositoryImpl]. /// /// [remoteDataSource] La source de données distante pour les utilisateurs UserRepositoryImpl({required this.remoteDataSource}); /// Source de données distante pour les opérations sur les utilisateurs final UserRemoteDataSource remoteDataSource; /// Log un message si le mode debug est activé. void _log(String message) { AppLogger.d(message, tag: 'UserRepositoryImpl'); } /// Récupère un utilisateur par son ID depuis la source de données distante. /// /// [id] L'identifiant de l'utilisateur /// /// Returns [Right] avec l'utilisateur si succès, [Left] avec une [Failure] si erreur /// /// **Exemple:** /// ```dart /// final result = await repository.getUser('user123'); /// result.fold( /// (failure) => handleError(failure), /// (user) => displayUser(user), /// ); /// ``` @override Future> getUser(String id) async { _log('Récupération de l\'utilisateur $id'); try { if (id.isEmpty) { return const Left(ValidationFailure(message: 'L\'ID utilisateur ne peut pas être vide', field: 'id', )); } final userModel = await remoteDataSource.getUser(id); _log('Utilisateur $id récupéré avec succès'); return Right(userModel.toEntity()); } on UserNotFoundException catch (e) { _log('Utilisateur $id non trouvé: ${e.message}'); return Left(ServerFailure( message: e.message, code: 'USER_NOT_FOUND', statusCode: 404, )); } on ValidationException catch (e) { _log('Erreur de validation: ${e.message}'); return Left(ValidationFailure(message: e.message, field: e.field, )); } on ServerException catch (e) { _log('Erreur serveur: ${e.message}'); return Left(ServerFailure( message: e.message, statusCode: e.statusCode, )); } catch (e) { _log('Erreur inattendue: $e'); return Left(ServerFailure( message: 'Erreur lors de la récupération de l\'utilisateur: $e', )); } } /// Authentifie un utilisateur avec son email et mot de passe. /// /// [email] L'adresse email de l'utilisateur /// [password] Le mot de passe de l'utilisateur /// /// Returns [Right] avec l'utilisateur authentifié si succès, /// [Left] avec une [Failure] si erreur /// /// **Exemple:** /// ```dart /// final result = await repository.authenticateUser( /// 'user@example.com', /// 'password123', /// ); /// ``` Future> authenticateUser( String email, String password, ) async { _log('Authentification pour: $email'); try { if (email.isEmpty || password.isEmpty) { return const Left(ValidationFailure(message: 'L\'email et le mot de passe sont requis', )); } final userModel = await remoteDataSource.authenticateUser(email, password); _log('Authentification réussie pour: ${userModel.email}'); return Right(userModel.toEntity()); } on UnauthorizedException catch (e) { _log('Authentification échouée: ${e.message}'); return Left(AuthenticationFailure( message: e.message, code: 'UNAUTHORIZED', )); } on ValidationException catch (e) { _log('Erreur de validation: ${e.message}'); return Left(ValidationFailure(message: e.message, field: e.field, )); } on ServerException catch (e) { _log('Erreur serveur: ${e.message}'); return Left(ServerFailure( message: e.message, statusCode: e.statusCode, )); } catch (e) { _log('Erreur inattendue: $e'); return Left(ServerFailure( message: 'Erreur lors de l\'authentification: $e', )); } } /// Crée un nouvel utilisateur. /// /// [user] L'entité utilisateur à créer /// /// Returns [Right] avec l'utilisateur créé si succès, /// [Left] avec une [Failure] si erreur Future> createUser(User user) async { _log('Création d\'un nouvel utilisateur: ${user.email}'); try { final userModel = UserModel( userId: user.userId, userLastName: user.userLastName, userFirstName: user.userFirstName, email: user.email, motDePasse: user.motDePasse, profileImageUrl: user.profileImageUrl, eventsCount: user.eventsCount, friendsCount: user.friendsCount, postsCount: user.postsCount, visitedPlacesCount: user.visitedPlacesCount, ); final createdUser = await remoteDataSource.createUser(userModel); _log('Utilisateur créé avec succès: ${createdUser.userId}'); return Right(createdUser.toEntity()); } on ConflictException catch (e) { _log('Conflit lors de la création: ${e.message}'); return Left(ServerFailure( message: e.message, code: 'CONFLICT', statusCode: 409, )); } on ValidationException catch (e) { _log('Erreur de validation: ${e.message}'); return Left(ValidationFailure(message: e.message, field: e.field, )); } on ServerException catch (e) { _log('Erreur serveur: ${e.message}'); return Left(ServerFailure( message: e.message, statusCode: e.statusCode, )); } catch (e) { _log('Erreur inattendue: $e'); return Left(ServerFailure( message: 'Erreur lors de la création de l\'utilisateur: $e', )); } } /// Met à jour un utilisateur existant. /// /// [user] L'entité utilisateur avec les nouvelles données /// /// Returns [Right] avec l'utilisateur mis à jour si succès, /// [Left] avec une [Failure] si erreur Future> updateUser(User user) async { _log('Mise à jour de l\'utilisateur ${user.userId}'); try { final userModel = UserModel( userId: user.userId, userLastName: user.userLastName, userFirstName: user.userFirstName, email: user.email, motDePasse: user.motDePasse, profileImageUrl: user.profileImageUrl, eventsCount: user.eventsCount, friendsCount: user.friendsCount, postsCount: user.postsCount, visitedPlacesCount: user.visitedPlacesCount, ); final updatedUser = await remoteDataSource.updateUser(userModel); _log('Utilisateur ${user.userId} mis à jour avec succès'); return Right(updatedUser.toEntity()); } on UserNotFoundException catch (e) { _log('Utilisateur non trouvé: ${e.message}'); return Left(ServerFailure( message: e.message, code: 'USER_NOT_FOUND', statusCode: 404, )); } on ValidationException catch (e) { _log('Erreur de validation: ${e.message}'); return Left(ValidationFailure(message: e.message, field: e.field, )); } on ServerException catch (e) { _log('Erreur serveur: ${e.message}'); return Left(ServerFailure( message: e.message, statusCode: e.statusCode, )); } catch (e) { _log('Erreur inattendue: $e'); return Left(ServerFailure( message: 'Erreur lors de la mise à jour de l\'utilisateur: $e', )); } } /// Supprime un utilisateur. /// /// [id] L'identifiant de l'utilisateur à supprimer /// /// Returns [Right] avec `null` si succès, [Left] avec une [Failure] si erreur Future> deleteUser(String id) async { _log('Suppression de l\'utilisateur $id'); try { if (id.isEmpty) { return const Left(ValidationFailure(message: 'L\'ID utilisateur ne peut pas être vide', field: 'id', )); } await remoteDataSource.deleteUser(id); _log('Utilisateur $id supprimé avec succès'); return const Right(null); } on UserNotFoundException catch (e) { _log('Utilisateur non trouvé: ${e.message}'); return Left(ServerFailure( message: e.message, code: 'USER_NOT_FOUND', statusCode: 404, )); } on ValidationException catch (e) { _log('Erreur de validation: ${e.message}'); return Left(ValidationFailure(message: e.message, field: e.field, )); } on ServerException catch (e) { _log('Erreur serveur: ${e.message}'); return Left(ServerFailure( message: e.message, statusCode: e.statusCode, )); } catch (e) { _log('Erreur inattendue: $e'); return Left(ServerFailure( message: 'Erreur lors de la suppression de l\'utilisateur: $e', )); } } }