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 jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import java.util.HashSet; import java.util.List; 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 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."); } // 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); 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é // 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); 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 return new FriendshipReadFriendDetailsResponseDTO( user.getId(), // ID de l'utilisateur friend.getId(), // ID de l'ami friend.getNom(), // Nom de l'ami friend.getPrenoms(), 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 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 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 uniqueFriendKeys = new HashSet<>(); return friendships.stream() .map(friendship -> { Users friend = friendship.getUser().equals(user) ? friendship.getFriend() : friendship.getUser(); return new FriendshipReadFriendDetailsResponseDTO( user.getId(), friend.getId(), friend.getNom(), friend.getPrenoms(), 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 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 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 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 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 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 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(); } }