import 'package:equatable/equatable.dart'; import 'package:logger/logger.dart'; /// Enumération représentant les différents statuts possibles d'un ami. /// Utilisée pour éviter les erreurs de chaîne de caractères et faciliter les comparaisons. enum FriendStatus { pending, accepted, blocked, unknown } /// Classe [Friend] représentant un ami avec ses informations de base. /// Cette classe est conçue pour être utilisée dans des applications de haut niveau /// avec une gestion robuste des erreurs, des logs avancés, et une immuabilité stricte. /// /// Chaque instance de [Friend] est immuable et toute modification doit passer par [copyWith]. class Friend extends Equatable { /// Constructeur de la classe [Friend]. /// Initialisation avec des valeurs spécifiques pour `firstName` et `lastName`. /// La validation des valeurs est incluse pour garantir l'intégrité des données. Friend({ required this.friendId, this.friendFirstName = 'Ami inconnu', // Valeur par défaut pour éviter les champs vides this.friendLastName = '', this.email, this.imageUrl, this.status = FriendStatus.unknown, this.dateAdded, this.lastInteraction, this.isOnline = false, this.isBestFriend = false, this.hasKnownSinceChildhood = false, }) { assert(friendId.isNotEmpty, 'friendId ne doit pas être vide'); _logger.i( '[LOG] Création d\'un objet Friend : ID = $friendId, Nom = $friendFirstName $friendLastName',); } /// Méthode factory pour créer un objet [Friend] à partir d'un JSON. /// Inclut une validation approfondie pour vérifier l'intégrité des données. /// /// Retourne une instance de [Friend] ou null si les données sont incomplètes. factory Friend.fromJson(Map json) { _logger.i('[LOG] Conversion JSON -> Friend : $json'); if (json['friendId'] == null || (json['friendId'] as String).isEmpty) { _logger.e('[ERROR] friendId manquant ou vide dans le JSON.'); throw ArgumentError('friendId est requis pour créer un objet Friend'); } return Friend( friendId: json['friendId'] as String, friendFirstName: json['friendFirstName'] as String? ?? 'Ami inconnu', friendLastName: json['friendLastName'] as String? ?? '', email: json['email'] as String?, imageUrl: json['friendProfileImageUrl'] as String?, status: _parseStatus(json['status'] as String?), isOnline: json['isOnline'] == true, isBestFriend: json['isBestFriend'] == true, hasKnownSinceChildhood: json['hasKnownSinceChildhood'] == true, ); } final String friendId; // ID unique de l'ami, requis et non-nullable final String friendFirstName; // Prénom de l'ami, non-nullable pour garantir une intégrité des données final String friendLastName; // Nom de famille, non-nullable final String? email; // Adresse e-mail, optionnelle mais typiquement présente final String? imageUrl; // URL de l'image de profil, optionnelle final FriendStatus status; // Statut de l'ami, avec une valeur par défaut `unknown` final String? dateAdded; final String? lastInteraction; final bool? isOnline; final bool? isBestFriend; final bool? hasKnownSinceChildhood; /// Logger statique pour suivre toutes les actions et transformations liées à [Friend]. static final Logger _logger = Logger(); /// Méthode privée pour parser le champ `status` en type [FriendStatus]. /// Retourne [FriendStatus.unknown] si le statut est non reconnu. static FriendStatus _parseStatus(String? status) { switch (status?.toLowerCase()) { case 'pending': return FriendStatus.pending; case 'accepted': return FriendStatus.accepted; case 'blocked': return FriendStatus.blocked; default: return FriendStatus.unknown; } } /// Sérialise un objet [Friend] en JSON pour être transmis à l'API. /// Les logs incluent le temps de traitement pour les optimisations de performance. Map toJson() { final json = { 'friendId': friendId, 'friendFirstName': friendFirstName, 'friendLastName': friendLastName, 'email': email, 'friendProfileImageUrl': imageUrl, 'status': status.name, 'isOnline': isOnline, 'isBestFriend': isBestFriend, 'hasKnownSinceChildhood': hasKnownSinceChildhood, }; _logger.i('[LOG] Conversion Friend -> JSON : $json'); return json; } /// Méthode [copyWith] pour cloner un objet `Friend` en modifiant certains attributs. /// Facilite la modification immuable des propriétés sans affecter l'instance actuelle. /// /// Log chaque copie pour surveiller l'état des données. Friend copyWith( {String? friendId, String? friendFirstName, String? friendLastName, String? email, String? imageUrl, FriendStatus? status, String? lastInteraction, String? dateAdded, bool? isOnline, bool? isBestFriend, bool? hasKnownSinceChildhood,}) { final newFriend = Friend( friendId: friendId ?? this.friendId, friendFirstName: friendFirstName ?? this.friendFirstName, friendLastName: friendLastName ?? this.friendLastName, email: email ?? this.email, imageUrl: imageUrl ?? this.imageUrl, status: status ?? this.status, isOnline: isOnline ?? this.isOnline, isBestFriend: isBestFriend ?? this.isBestFriend, hasKnownSinceChildhood: hasKnownSinceChildhood ?? this.hasKnownSinceChildhood, ); _logger.i( '[LOG] Création d\'une copie modifiée de Friend : ID = ${newFriend.friendId}',); return newFriend; } /// Propriétés utilisées pour comparer les objets [Friend], /// facilitant l'utilisation dans des listes et des ensembles. @override List get props => [ friendId, friendFirstName, friendLastName, email, imageUrl, status, isOnline, isBestFriend, hasKnownSinceChildhood, ]; }