import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart' as http; import 'package:logger/logger.dart'; import '../../core/constants/urls.dart'; import '../../domain/entities/friend.dart'; import 'friends_repository.dart'; /// Implémentation de [FriendsRepository] pour gérer les appels API relatifs aux amis. /// Chaque action est loguée pour une traçabilité complète et une gestion des erreurs avancée. class FriendsRepositoryImpl implements FriendsRepository { final http.Client client; final Logger _logger = Logger(); // Logger pour suivre toutes les actions. FriendsRepositoryImpl({required this.client}); /// Récupère la liste paginée des amis pour un utilisateur donné via l'API. /// /// [userId] : Identifiant unique de l'utilisateur. /// [page] : Page actuelle pour la pagination. /// [size] : Nombre d'amis par page. /// /// Retourne une liste d'objets [Friend] ou une liste vide en cas d'erreur. @override Future> fetchFriends(String userId, int page, int size) async { try { _logger.i("[LOG] Chargement des amis pour l'utilisateur : $userId, page : $page, taille : $size"); final uri = Uri.parse('${Urls.baseUrl}/friends/list/$userId?page=$page&size=$size'); _logger.d('[LOG] URL appelée : $uri'); final response = await client.get(uri); if (response.statusCode == 200) { _logger.i("[LOG] Liste des amis récupérée avec succès."); final List friendsJson = json.decode(response.body); _logger.i("[LOG] Nombre d'amis récupérés (excluant l'utilisateur lui-même) : ${friendsJson.length}"); return friendsJson.map((json) { _logger.i("[LOG] Conversion JSON -> Friend : $json"); final friend = Friend.fromJson(json as Map); _logger.i("[LOG] Création d'un objet Friend : ID = ${friend.friendId}, Nom = ${friend.friendFirstName} ${friend.friendLastName}"); return friend; }).toList(); } else { _logger.e("[ERROR] Échec de la récupération des amis. Code HTTP : ${response.statusCode}"); return []; } } catch (e) { _logger.e("[ERROR] Exception lors de la récupération des amis : $e"); return []; } } /// Envoie une demande pour ajouter un nouvel ami via l'API. /// /// [friend] : Objet [Friend] représentant l'ami à ajouter. /// /// Loggue chaque étape et lève une exception en cas d'erreur. @override Future addFriend(Friend friend) async { try { _logger.i("[LOG] Tentative d'ajout de l'ami : ${friend.friendFirstName} ${friend.friendLastName}"); final uri = Uri.parse('${Urls.baseUrl}/friends/send'); final response = await client.post( uri, headers: {'Content-Type': 'application/json'}, body: json.encode(friend.toJson()), ); if (response.statusCode == 200) { _logger.i("[LOG] Ami ajouté avec succès : ${friend.friendId}"); } else { _logger.e("[ERROR] Échec lors de l'ajout de l'ami. Code HTTP : ${response.statusCode}"); throw Exception("Erreur lors de l'ajout de l'ami"); } } catch (e) { _logger.e("[ERROR] Exception lors de l'ajout de l'ami : $e"); rethrow; } } /// Supprime un ami existant via l'API. /// /// [friendId] : Identifiant unique de l'ami à supprimer. /// /// Loggue l'action et lève une exception en cas d'erreur. @override Future removeFriend(String friendId) async { try { _logger.i("[LOG] Tentative de suppression de l'ami avec l'ID : $friendId"); final uri = Uri.parse('${Urls.baseUrl}/friends/$friendId'); final response = await client.delete(uri); if (response.statusCode == 200) { _logger.i("[LOG] Ami supprimé avec succès : $friendId"); } else { _logger.e("[ERROR] Échec lors de la suppression de l'ami. Code HTTP : ${response.statusCode}"); throw Exception("Erreur lors de la suppression de l'ami"); } } catch (e) { _logger.e("[ERROR] Exception lors de la suppression de l'ami : $e"); rethrow; } } /// Récupère les détails d'un ami en utilisant son identifiant `friendId`. /// /// [friendId] : Identifiant unique de l'ami. /// [userId] : Identifiant unique de l'utilisateur connecté. /// /// Retourne un `Future` avec les informations de l'ami ou `null` en cas d'échec. @override Future getFriendDetails(String friendId, String userId) async { try { _logger.i("[LOG] Récupération des détails de l'ami avec ID : $friendId pour l'utilisateur : $userId"); final uri = Uri.parse('${Urls.baseUrl}/friends/details'); _logger.d("[LOG] URL pour les détails de l'ami : $uri"); final headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; final body = jsonEncode({ 'friendId': friendId, 'userId': userId, }); final response = await client.post(uri, headers: headers, body: body); _logger.d("[LOG] Réponse de l'API : ${response.body}"); if (response.statusCode == 200) { final friendJson = json.decode(response.body); _logger.i("[LOG] Détails de l'ami récupérés : $friendJson"); return Friend.fromJson(friendJson); } else { _logger.e("[ERROR] Échec de la récupération des détails. Code HTTP : ${response.statusCode}"); return null; } } catch (e) { _logger.e("[ERROR] Exception lors de la récupération des détails de l'ami : $e"); return null; } } /// Met à jour le statut d'un ami (par exemple, "accepté", "bloqué"). /// /// [friendId] : Identifiant unique de l'ami. /// [status] : Nouveau statut sous forme de chaîne de caractères. /// /// Loggue chaque étape et lève une exception en cas d'échec. @override Future updateFriendStatus(String friendId, String status) async { try { _logger.i("[LOG] Mise à jour du statut de l'ami avec l'ID : $friendId, nouveau statut : $status"); final uri = Uri.parse('${Urls.baseUrl}/friends/$friendId/status'); final response = await client.patch( uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode({'status': status}), ); if (response.statusCode == 200) { _logger.i("[LOG] Statut de l'ami mis à jour avec succès : $friendId"); } else { _logger.e("[ERROR] Erreur lors de la mise à jour du statut. Code HTTP : ${response.statusCode}"); throw Exception("Erreur lors de la mise à jour du statut"); } } catch (e) { _logger.e("[ERROR] Exception lors de la mise à jour du statut de l'ami : $e"); rethrow; } } }