- Migration de Jakarta WebSocket vers Quarkus WebSockets Next - Implémentation de l'architecture Kafka pour événements temps réel - Ajout des DTOs d'événements (NotificationEvent, ChatMessageEvent, ReactionEvent, PresenceEvent) - Création des bridges Kafka → WebSocket (NotificationKafkaBridge, ChatKafkaBridge, ReactionKafkaBridge) - Mise à jour des services pour publier dans Kafka au lieu d'appeler directement WebSocket - Suppression des classes obsolètes (ChatWebSocket, NotificationWebSocket) - Correction de l'injection des paramètres path dans WebSockets Next (utilisation de connection.pathParam) - Ajout des migrations DB pour bookings, promotions, business hours, amenities, reviews - Mise à jour de la configuration application.properties pour Kafka et WebSockets Next - Mise à jour .gitignore pour ignorer les fichiers de logs
543 lines
23 KiB
Java
543 lines
23 KiB
Java
package com.lions.dev.service;
|
|
|
|
import com.lions.dev.dto.request.friends.FriendshipCreateOneRequestDTO;
|
|
import com.lions.dev.dto.request.friends.FriendshipReadFriendDetailsRequestDTO;
|
|
import com.lions.dev.dto.request.friends.FriendshipReadStatusRequestDTO;
|
|
import com.lions.dev.dto.response.friends.FriendshipCreateOneResponseDTO;
|
|
import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO;
|
|
import com.lions.dev.dto.response.friends.FriendshipReadStatusResponseDTO;
|
|
import com.lions.dev.entity.friends.Friendship;
|
|
import com.lions.dev.entity.friends.FriendshipStatus;
|
|
import com.lions.dev.entity.users.Users;
|
|
import com.lions.dev.exception.FriendshipNotFoundException;
|
|
import com.lions.dev.exception.UserNotFoundException;
|
|
import com.lions.dev.repository.FriendshipRepository;
|
|
import com.lions.dev.repository.UsersRepository;
|
|
import com.lions.dev.dto.events.NotificationEvent;
|
|
import org.eclipse.microprofile.reactive.messaging.Channel;
|
|
import org.eclipse.microprofile.reactive.messaging.Emitter;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.transaction.Transactional;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import org.jboss.logging.Logger;
|
|
|
|
/**
|
|
* Service pour gérer les relations d'amitié.
|
|
* Contient la logique métier pour envoyer, accepter, rejeter, et supprimer des relations d'amitié.
|
|
*/
|
|
@ApplicationScoped
|
|
public class FriendshipService {
|
|
|
|
@Inject
|
|
FriendshipRepository friendshipRepository; // Injecte le repository des amitiés
|
|
@Inject
|
|
UsersRepository usersRepository; // Injecte le repository des utilisateurs
|
|
@Inject
|
|
NotificationService notificationService; // Injecte le service de notifications
|
|
|
|
@Inject
|
|
@Channel("notifications")
|
|
Emitter<NotificationEvent> notificationEmitter; // v2.0 - Publie dans Kafka
|
|
|
|
private static final Logger logger = Logger.getLogger(FriendshipService.class);
|
|
|
|
/**
|
|
* Envoie une demande d'amitié entre deux utilisateurs.
|
|
*
|
|
* @param request DTO contenant les informations sur l'utilisateur et l'ami.
|
|
* @return Le DTO de la relation d'amitié créée.
|
|
*/
|
|
@Transactional
|
|
public FriendshipCreateOneResponseDTO sendFriendRequest(FriendshipCreateOneRequestDTO request) {
|
|
logger.info("[LOG] Envoi d'une demande d'amitié de l'utilisateur " + request.getUserId() + " à l'utilisateur " + request.getFriendId());
|
|
|
|
// Récupérer les utilisateurs concernés
|
|
Users user = usersRepository.findById(request.getUserId());
|
|
Users friend = usersRepository.findById(request.getFriendId());
|
|
|
|
if (user == null || friend == null) {
|
|
String notFoundId = user == null ? request.getUserId().toString() : request.getFriendId().toString();
|
|
logger.error("[ERROR] Utilisateur non trouvé pour l'ID : " + notFoundId);
|
|
throw new UserNotFoundException("Utilisateur avec l'ID " + notFoundId + " introuvable.");
|
|
}
|
|
|
|
// VALIDATION: Empêcher l'utilisateur de s'ajouter lui-même comme ami
|
|
if (user.getId().equals(friend.getId())) {
|
|
logger.error("[ERROR] Tentative d'ajout de soi-même comme ami bloquée pour l'utilisateur : " + user.getId());
|
|
throw new IllegalArgumentException("Vous ne pouvez pas vous ajouter vous-même comme ami.");
|
|
}
|
|
|
|
// Vérifier s'il existe déjà une relation d'amitié
|
|
Friendship existingFriendship = friendshipRepository.findByUsers(user, friend).orElse(null);
|
|
if (existingFriendship != null) {
|
|
logger.error("[ERROR] Relation d'amitié déjà existante entre les utilisateurs.");
|
|
throw new IllegalArgumentException("Relation d'amitié déjà existante.");
|
|
}
|
|
|
|
// Créer et persister une nouvelle relation d'amitié
|
|
Friendship friendship = new Friendship(user, friend, FriendshipStatus.PENDING);
|
|
friendshipRepository.persist(friendship);
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Map<String, Object> notificationData = new HashMap<>();
|
|
notificationData.put("requestId", friendship.getId().toString());
|
|
notificationData.put("senderId", user.getId().toString());
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
notificationData.put("senderName", user.getFirstName() + " " + user.getLastName());
|
|
notificationData.put("senderProfileImage", user.getProfileImageUrl() != null ? user.getProfileImageUrl() : "");
|
|
|
|
NotificationEvent event = new NotificationEvent(
|
|
friend.getId().toString(), // userId destinataire (clé Kafka)
|
|
"friend_request_received",
|
|
notificationData
|
|
);
|
|
|
|
notificationEmitter.send(event);
|
|
logger.info("[LOG] Événement friend_request_received publié dans Kafka pour : " + friend.getId());
|
|
} catch (Exception e) {
|
|
logger.error("[ERROR] Erreur lors de la publication dans Kafka : " + e.getMessage(), e);
|
|
// Ne pas bloquer la demande d'amitié si Kafka échoue
|
|
}
|
|
|
|
logger.info("[LOG] Demande d'amitié envoyée avec succès.");
|
|
return new FriendshipCreateOneResponseDTO(friendship);
|
|
}
|
|
|
|
/**
|
|
* Accepter une demande d'amitié.
|
|
*
|
|
* @param friendshipId ID de la demande à accepter.
|
|
* @return Le DTO de la relation d'amitié acceptée.
|
|
*/
|
|
@Transactional
|
|
public FriendshipCreateOneResponseDTO acceptFriendRequest(UUID friendshipId) {
|
|
// Vérification de l'ID de la demande d'amitié
|
|
if (friendshipId == null) {
|
|
logger.error(String.format("[ERROR] L'ID de la demande d'amitié est nul."));
|
|
throw new IllegalArgumentException("L'ID de la demande d'amitié est nul.");
|
|
}
|
|
|
|
// Rechercher l'amitié dans la base de données
|
|
Friendship friendship = friendshipRepository.findById(friendshipId);
|
|
|
|
// Si l'amitié n'est pas trouvée, lever une exception
|
|
if (friendship == null) {
|
|
logger.error(String.format("[ERROR] Demande d'amitié introuvable pour l'ID: %s", friendshipId)); // Correctement formaté
|
|
throw new FriendshipNotFoundException("Demande d'amitié introuvable.");
|
|
}
|
|
|
|
// Vérifier que la demande n'est pas déjà acceptée
|
|
if (friendship.getStatus() == FriendshipStatus.ACCEPTED) {
|
|
logger.error(String.format("[ERROR] Demande d'amitié déjà acceptée pour l'ID: %s", friendshipId)); // Correctement formaté
|
|
throw new IllegalArgumentException("Demande d'amitié déjà acceptée.");
|
|
}
|
|
|
|
// Accepter la demande
|
|
friendship.setStatus(FriendshipStatus.ACCEPTED);
|
|
friendshipRepository.persist(friendship);
|
|
|
|
// Log de succès
|
|
logger.info(String.format("[LOG] Demande d'amitié acceptée avec succès pour l'ID: %s", friendshipId)); // Correctement formaté
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Users user = friendship.getUser();
|
|
Users friend = friendship.getFriend();
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
String friendName = friend.getFirstName() + " " + friend.getLastName();
|
|
|
|
Map<String, Object> notificationData = new HashMap<>();
|
|
notificationData.put("acceptedBy", friendName);
|
|
notificationData.put("friendshipId", friendshipId.toString());
|
|
notificationData.put("accepterId", friend.getId().toString());
|
|
notificationData.put("accepterProfileImage", friend.getProfileImageUrl() != null ? friend.getProfileImageUrl() : "");
|
|
|
|
NotificationEvent event = new NotificationEvent(
|
|
user.getId().toString(), // userId émetteur (destinataire de la notification)
|
|
"friend_request_accepted",
|
|
notificationData
|
|
);
|
|
|
|
notificationEmitter.send(event);
|
|
logger.info("[LOG] Événement friend_request_accepted publié dans Kafka pour : " + user.getId());
|
|
} catch (Exception e) {
|
|
logger.error("[ERROR] Erreur lors de la publication dans Kafka : " + e.getMessage(), e);
|
|
// Ne pas bloquer l'acceptation si Kafka échoue
|
|
}
|
|
|
|
// Créer des notifications pour les deux utilisateurs
|
|
try {
|
|
Users user = friendship.getUser();
|
|
Users friend = friendship.getFriend();
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
String userName = user.getFirstName() + " " + user.getLastName();
|
|
String friendName = friend.getFirstName() + " " + friend.getLastName();
|
|
|
|
// Notification pour l'utilisateur qui a envoyé la demande
|
|
notificationService.createNotification(
|
|
"Demande d'amitié acceptée",
|
|
friendName + " a accepté votre demande d'amitié",
|
|
"friend",
|
|
user.getId(),
|
|
null
|
|
);
|
|
|
|
// Notification pour l'utilisateur qui a accepté la demande
|
|
notificationService.createNotification(
|
|
"Nouveaux amis",
|
|
"Vous êtes maintenant ami(e) avec " + userName,
|
|
"friend",
|
|
friend.getId(),
|
|
null
|
|
);
|
|
|
|
logger.info("[LOG] Notifications d'amitié créées pour les deux utilisateurs");
|
|
} catch (Exception e) {
|
|
logger.error("[ERROR] Erreur lors de la création des notifications d'amitié : " + e.getMessage());
|
|
}
|
|
|
|
// Retourner la réponse avec les informations de la relation d'amitié
|
|
return new FriendshipCreateOneResponseDTO(friendship);
|
|
}
|
|
|
|
/**
|
|
* Rejeter une demande d'amitié.
|
|
*
|
|
* @param friendshipId ID de la demande à rejeter.
|
|
*/
|
|
@Transactional
|
|
public void rejectFriendRequest(UUID friendshipId) {
|
|
Friendship friendship = friendshipRepository.findById(friendshipId);
|
|
if (friendship == null) {
|
|
throw new FriendshipNotFoundException("Demande d'amitié introuvable.");
|
|
}
|
|
|
|
friendship.setStatus(FriendshipStatus.REJECTED);
|
|
friendshipRepository.persist(friendship);
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Users user = friendship.getUser();
|
|
|
|
Map<String, Object> notificationData = new HashMap<>();
|
|
notificationData.put("friendshipId", friendshipId.toString());
|
|
notificationData.put("rejectedAt", System.currentTimeMillis());
|
|
|
|
NotificationEvent event = new NotificationEvent(
|
|
user.getId().toString(), // userId émetteur (destinataire de la notification)
|
|
"friend_request_rejected",
|
|
notificationData
|
|
);
|
|
|
|
notificationEmitter.send(event);
|
|
logger.info("[LOG] Événement friend_request_rejected publié dans Kafka pour : " + user.getId());
|
|
} catch (Exception e) {
|
|
logger.error("[ERROR] Erreur lors de la publication dans Kafka : " + e.getMessage(), e);
|
|
// Ne pas bloquer le rejet si Kafka échoue
|
|
}
|
|
|
|
logger.info("[LOG] Demande d'amitié rejetée.");
|
|
}
|
|
|
|
/**
|
|
* Supprimer une relation d'amitié.
|
|
*
|
|
* @param friendshipId ID de la relation à supprimer.
|
|
*/
|
|
@Transactional
|
|
public void removeFriend(UUID friendshipId) {
|
|
Friendship friendship = friendshipRepository.findById(friendshipId);
|
|
if (friendship == null) {
|
|
throw new FriendshipNotFoundException("Relation d'amitié introuvable.");
|
|
}
|
|
|
|
friendshipRepository.delete(friendship);
|
|
logger.info("[LOG] Relation d'amitié supprimée.");
|
|
}
|
|
|
|
/**
|
|
* Récupère les détails d'un ami spécifique pour un utilisateur donné.
|
|
*
|
|
* @param request DTO contenant l'ID de l'utilisateur et de l'ami.
|
|
* @return Le DTO des détails de l'ami.
|
|
*/
|
|
@Transactional
|
|
public FriendshipReadFriendDetailsResponseDTO getFriendDetails(
|
|
FriendshipReadFriendDetailsRequestDTO request) {
|
|
logger.info("[LOG] Tentative de récupération des détails de l'ami avec l'ID : "
|
|
+ request.getFriendId() + " pour l'utilisateur : " + request.getUserId());
|
|
|
|
// Récupération de l'utilisateur et de l'ami
|
|
Users user = usersRepository.findById(request.getUserId());
|
|
Users friend = usersRepository.findById(request.getFriendId());
|
|
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur introuvable avec l'ID : " + request.getUserId());
|
|
throw new UserNotFoundException("Utilisateur introuvable avec l'ID " + request.getUserId());
|
|
}
|
|
|
|
if (friend == null) {
|
|
logger.error("[ERROR] Ami introuvable avec l'ID : " + request.getFriendId());
|
|
throw new UserNotFoundException("Ami introuvable avec l'ID " + request.getFriendId());
|
|
}
|
|
|
|
// Récupérer la relation d'amitié entre les deux utilisateurs
|
|
Friendship friendship = friendshipRepository.findByUsers(user, friend).orElse(null);
|
|
if (friendship == null) {
|
|
logger.error("[ERROR] Aucune relation d'amitié trouvée entre l'utilisateur et l'ami.");
|
|
throw new FriendshipNotFoundException("Relation d'amitié introuvable.");
|
|
}
|
|
|
|
logger.info("[LOG] Détails de l'ami récupérés avec succès pour l'utilisateur : "
|
|
+ user.getId() + ", ami ID : " + friend.getId());
|
|
|
|
// Création du DTO de réponse à partir des informations de l'ami et de la relation
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
return new FriendshipReadFriendDetailsResponseDTO(
|
|
user.getId(), // ID de l'utilisateur
|
|
friend.getId(), // ID de l'ami
|
|
friend.getLastName(), // Nom de famille de l'ami (v2.0)
|
|
friend.getFirstName(), // Prénom de l'ami (v2.0)
|
|
friend.getEmail(), // Email de l'ami
|
|
friend.getProfileImageUrl(), // URL de l'image de profil de l'ami
|
|
friendship.getStatus(), // Statut de la relation
|
|
friendship.getCreatedAt(), // Date de création de la relation
|
|
friendship.getUpdatedAt() // Date de mise à jour de la relation
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Récupérer la liste des amis d'un utilisateur.
|
|
*
|
|
* @param userId ID de l'utilisateur.
|
|
* @param page Numéro de la page.
|
|
* @param size Taille de la page.
|
|
* @return Liste paginée des relations d'amitié.
|
|
*/
|
|
public List<FriendshipReadFriendDetailsResponseDTO> listFriends(UUID userId, int page, int size) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur non trouvé.");
|
|
throw new UserNotFoundException("Utilisateur introuvable.");
|
|
}
|
|
|
|
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, page, size);
|
|
logger.info("[LOG] " + friendships.size() + " amis récupérés (avant filtrage des doublons).");
|
|
|
|
// Utilisation d'un ensemble pour stocker des clés uniques basées sur les IDs des amis
|
|
Set<String> uniqueFriendKeys = new HashSet<>();
|
|
|
|
return friendships.stream()
|
|
.map(friendship -> {
|
|
Users friend = friendship.getUser().equals(user) ? friendship.getFriend() : friendship.getUser();
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
return new FriendshipReadFriendDetailsResponseDTO(
|
|
user.getId(),
|
|
friend.getId(),
|
|
friend.getLastName(), // v2.0
|
|
friend.getFirstName(), // v2.0
|
|
friend.getEmail(),
|
|
friend.getProfileImageUrl(),
|
|
friendship.getStatus(),
|
|
friendship.getCreatedAt(),
|
|
friendship.getUpdatedAt()
|
|
);
|
|
})
|
|
.filter(dto -> uniqueFriendKeys.add(dto.getUserId().toString() + "-" + dto.getFriendId().toString()))
|
|
.limit(size) // Limite la taille au paramètre 'size' requis
|
|
.toList();
|
|
}
|
|
|
|
/**
|
|
* Récupérer les demandes d'amitié avec un statut spécifique.
|
|
*
|
|
* @param request DTO contenant les informations de filtrage (statut).
|
|
* @return Liste des demandes d'amitié avec le statut spécifié.
|
|
*/
|
|
public List<FriendshipReadStatusResponseDTO> listFriendRequestsByStatus(FriendshipReadStatusRequestDTO request) {
|
|
Users user = usersRepository.findById(request.getUserId());
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur non trouvé.");
|
|
throw new UserNotFoundException("Utilisateur introuvable.");
|
|
}
|
|
|
|
// Récupérer les demandes d'amitié selon le statut
|
|
List<Friendship> friendships = friendshipRepository.findByUserAndStatus(user, request.getStatus(), request.getPage() - 1, request.getSize());
|
|
logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées.");
|
|
|
|
return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList();
|
|
}
|
|
|
|
/**
|
|
* Récupérer les demandes d'amitié envoyées par un utilisateur.
|
|
*
|
|
* @param userId ID de l'utilisateur.
|
|
* @param page Numéro de la page.
|
|
* @param size Taille de la page.
|
|
* @return Liste des demandes d'amitié envoyées.
|
|
*/
|
|
public List<FriendshipReadStatusResponseDTO> listSentFriendRequests(UUID userId, int page, int size) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur non trouvé.");
|
|
throw new UserNotFoundException("Utilisateur introuvable.");
|
|
}
|
|
|
|
List<Friendship> friendships = friendshipRepository.findSentRequestsByUser(user, FriendshipStatus.PENDING, page - 1, size);
|
|
logger.info("[LOG] " + friendships.size() + " demandes d'amitié envoyées récupérées.");
|
|
|
|
return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList();
|
|
}
|
|
|
|
/**
|
|
* Récupérer les demandes d'amitié reçues par un utilisateur.
|
|
*
|
|
* @param userId ID de l'utilisateur.
|
|
* @param page Numéro de la page.
|
|
* @param size Taille de la page.
|
|
* @return Liste des demandes d'amitié reçues.
|
|
*/
|
|
public List<FriendshipReadStatusResponseDTO> listReceivedFriendRequests(UUID userId, int page, int size) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur non trouvé.");
|
|
throw new UserNotFoundException("Utilisateur introuvable.");
|
|
}
|
|
|
|
List<Friendship> friendships = friendshipRepository.findReceivedRequestsByUser(user, FriendshipStatus.PENDING, page - 1, size);
|
|
logger.info("[LOG] " + friendships.size() + " demandes d'amitié reçues récupérées.");
|
|
|
|
return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList();
|
|
}
|
|
|
|
/**
|
|
* Récupérer les suggestions d'amis pour un utilisateur.
|
|
*
|
|
* L'algorithme suggère des utilisateurs basés sur :
|
|
* 1. Amis d'amis (utilisateurs qui ont des amis en commun)
|
|
* 2. Utilisateurs récents (qui ne sont ni amis ni ont de demandes en attente)
|
|
*
|
|
* @param userId ID de l'utilisateur.
|
|
* @param limit Nombre maximum de suggestions à retourner.
|
|
* @return Liste des suggestions d'amis.
|
|
*/
|
|
public List<com.lions.dev.dto.response.users.FriendSuggestionResponseDTO> getFriendSuggestions(UUID userId, int limit) {
|
|
logger.info("[LOG] Récupération des suggestions d'amis pour l'utilisateur : " + userId);
|
|
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[ERROR] Utilisateur non trouvé.");
|
|
throw new UserNotFoundException("Utilisateur introuvable.");
|
|
}
|
|
|
|
// Récupérer tous les amis actuels de l'utilisateur (ACCEPTED)
|
|
// Utiliser une taille de page élevée pour récupérer tous les résultats
|
|
List<Friendship> currentFriendships = friendshipRepository.findByUserAndStatus(user, FriendshipStatus.ACCEPTED, 0, 10000);
|
|
Set<UUID> currentFriendIds = new HashSet<>();
|
|
for (Friendship friendship : currentFriendships) {
|
|
// Ajouter les IDs des amis (que l'utilisateur ait envoyé ou reçu la demande)
|
|
if (friendship.getUser().getId().equals(userId)) {
|
|
currentFriendIds.add(friendship.getFriend().getId());
|
|
} else {
|
|
currentFriendIds.add(friendship.getUser().getId());
|
|
}
|
|
}
|
|
|
|
// Récupérer toutes les demandes en attente pour exclure ces utilisateurs
|
|
List<Friendship> pendingFriendships = friendshipRepository.findByUserAndStatus(user, FriendshipStatus.PENDING, 0, 10000);
|
|
Set<UUID> pendingUserIds = new HashSet<>();
|
|
for (Friendship friendship : pendingFriendships) {
|
|
if (friendship.getUser().getId().equals(userId)) {
|
|
pendingUserIds.add(friendship.getFriend().getId());
|
|
} else {
|
|
pendingUserIds.add(friendship.getUser().getId());
|
|
}
|
|
}
|
|
|
|
// Map pour compter les amis en commun
|
|
Map<UUID, Integer> mutualFriendsCount = new HashMap<>();
|
|
|
|
// Pour chaque ami, trouver ses amis (amis d'amis)
|
|
for (UUID friendId : currentFriendIds) {
|
|
Users friend = usersRepository.findById(friendId);
|
|
if (friend == null) continue;
|
|
|
|
List<Friendship> friendsOfFriend = friendshipRepository.findByUserAndStatus(friend, FriendshipStatus.ACCEPTED, 0, 10000);
|
|
|
|
for (Friendship fof : friendsOfFriend) {
|
|
UUID potentialFriendId;
|
|
if (fof.getUser().getId().equals(friendId)) {
|
|
potentialFriendId = fof.getFriend().getId();
|
|
} else {
|
|
potentialFriendId = fof.getUser().getId();
|
|
}
|
|
|
|
// Exclure l'utilisateur lui-même, ses amis actuels et les demandes en attente
|
|
if (!potentialFriendId.equals(userId) &&
|
|
!currentFriendIds.contains(potentialFriendId) &&
|
|
!pendingUserIds.contains(potentialFriendId)) {
|
|
mutualFriendsCount.put(potentialFriendId, mutualFriendsCount.getOrDefault(potentialFriendId, 0) + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Trier par nombre d'amis en commun (décroissant)
|
|
List<Map.Entry<UUID, Integer>> sortedSuggestions = mutualFriendsCount.entrySet()
|
|
.stream()
|
|
.sorted(Map.Entry.<UUID, Integer>comparingByValue().reversed())
|
|
.limit(limit)
|
|
.toList();
|
|
|
|
// Créer les DTOs
|
|
List<com.lions.dev.dto.response.users.FriendSuggestionResponseDTO> suggestions = new ArrayList<>();
|
|
for (Map.Entry<UUID, Integer> entry : sortedSuggestions) {
|
|
Users suggestedUser = usersRepository.findById(entry.getKey());
|
|
if (suggestedUser != null) {
|
|
String reason = entry.getValue() > 1
|
|
? entry.getValue() + " amis en commun"
|
|
: "1 ami en commun";
|
|
suggestions.add(new com.lions.dev.dto.response.users.FriendSuggestionResponseDTO(
|
|
suggestedUser,
|
|
entry.getValue(),
|
|
reason
|
|
));
|
|
}
|
|
}
|
|
|
|
// Si pas assez de suggestions, ajouter des utilisateurs récents
|
|
if (suggestions.size() < limit) {
|
|
int remaining = limit - suggestions.size();
|
|
Set<UUID> excludedIds = new HashSet<>(currentFriendIds);
|
|
excludedIds.addAll(pendingUserIds);
|
|
excludedIds.add(userId);
|
|
excludedIds.addAll(mutualFriendsCount.keySet());
|
|
|
|
// Récupérer des utilisateurs récents qui ne sont pas dans les exclusions
|
|
List<Users> recentUsers = usersRepository.findAll()
|
|
.stream()
|
|
.filter(u -> !excludedIds.contains(u.getId()))
|
|
.limit(remaining)
|
|
.toList();
|
|
|
|
for (Users recentUser : recentUsers) {
|
|
suggestions.add(new com.lions.dev.dto.response.users.FriendSuggestionResponseDTO(
|
|
recentUser,
|
|
0,
|
|
"Nouvel utilisateur"
|
|
));
|
|
}
|
|
}
|
|
|
|
logger.info("[LOG] " + suggestions.size() + " suggestions d'amis générées.");
|
|
return suggestions;
|
|
}
|
|
}
|