package com.lions.dev.resource; 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.FriendshipStatus; import com.lions.dev.exception.UserNotFoundException; import com.lions.dev.service.FriendshipService; import jakarta.inject.Inject; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.UUID; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.media.Content; import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; /** * Ressource REST pour gérer les amitiés. Ce contrôleur expose des endpoints pour envoyer, accepter, * rejeter et supprimer des demandes d'amitié. Toutes les opérations sont loguées pour faciliter le * suivi en temps réel. */ @Path("/friends") @Produces(MediaType.APPLICATION_JSON) // Assure que la réponse sera en JSON @Consumes(MediaType.APPLICATION_JSON) // Assure que la requête attend du JSON @Tag(name = "Friendship", description = "Opérations liées à la gestion des amis") public class FriendshipResource { @Inject FriendshipService friendshipService; // Injection du service d'amitié private static final Logger logger = Logger.getLogger(FriendshipResource.class); /** * Envoie une demande d'amitié. * * @param request DTO contenant l'ID de l'utilisateur qui envoie la demande et l'utilisateur qui * la reçoit. * @return La relation d'amitié créée. */ @POST @Path("/send") @Operation( summary = "Envoyer une demande d'amitié", description = "Permet à un utilisateur d'envoyer une demande d'amitié") @APIResponses({ @APIResponse( responseCode = "200", description = "Demande d'amitié envoyée avec succès", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipCreateOneResponseDTO.class))), @APIResponse(responseCode = "400", description = "Requête invalide"), @APIResponse( responseCode = "500", description = "Erreur serveur lors de l'envoi de la demande d'amitié") }) public Response sendFriendRequest(@Valid @NotNull FriendshipCreateOneRequestDTO request) { logger.info( "[LOG] Reçu une demande pour envoyer une demande d'amitié de l'utilisateur " + request.getUserId() + " à l'utilisateur " + request.getFriendId()); try { // Appel du service pour envoyer la demande d'amitié FriendshipCreateOneResponseDTO friendshipResponse = friendshipService.sendFriendRequest(request); logger.info( "[LOG] Demande d'amitié envoyée avec succès entre les utilisateurs " + friendshipResponse.getUserId() + " et " + friendshipResponse.getFriendId()); return Response.ok(friendshipResponse).build(); } catch (Exception e) { logger.error("[ERROR] Erreur lors de l'envoi de la demande d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de l'envoi de la demande d'amitié.\"}") .build(); } } /** * Accepte une demande d'amitié. * * @param friendshipId L'ID de la relation d'amitié à accepter. * @return La relation d'amitié acceptée. */ @PATCH @Path("/{friendshipId}/accept") @Operation( summary = "Accepter une demande d'amitié", description = "Accepte une demande d'amitié en attente") @APIResponses({ @APIResponse( responseCode = "200", description = "Demande d'amitié acceptée", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipCreateOneResponseDTO.class))), @APIResponse(responseCode = "404", description = "Demande d'amitié non trouvée"), @APIResponse( responseCode = "500", description = "Erreur lors de l'acceptation de la demande d'amitié") }) public Response acceptFriendRequest(@PathParam("friendshipId") UUID friendshipId) { logger.info( "[LOG] Reçu une demande pour accepter la demande d'amitié avec l'ID : " + friendshipId); try { FriendshipCreateOneResponseDTO friendshipResponse = friendshipService.acceptFriendRequest(friendshipId); logger.info( "[LOG] Demande d'amitié acceptée avec succès entre les utilisateurs " + friendshipResponse.getUserId() + " et " + friendshipResponse.getFriendId()); return Response.ok(friendshipResponse).build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de l'acceptation de la demande d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de l'acceptation de la demande d'amitié.\"}") .build(); } } /** * Rejette une demande d'amitié. * * @param friendshipId L'ID de la relation d'amitié à rejeter. * @return Confirmation de la demande rejetée. */ @PATCH @Path("/{friendshipId}/reject") @Operation( summary = "Rejeter une demande d'amitié", description = "Rejette une demande d'amitié en attente") @APIResponses({ @APIResponse(responseCode = "204", description = "Demande d'amitié rejetée"), @APIResponse(responseCode = "404", description = "Demande d'amitié non trouvée"), @APIResponse(responseCode = "500", description = "Erreur lors du rejet de la demande d'amitié") }) public Response rejectFriendRequest(@PathParam("friendshipId") UUID friendshipId) { logger.info( "[LOG] Reçu une demande pour rejeter la demande d'amitié avec l'ID : " + friendshipId); try { friendshipService.rejectFriendRequest(friendshipId); logger.info("[LOG] Demande d'amitié rejetée avec succès."); return Response.noContent().build(); } catch (Exception e) { logger.error("[ERROR] Erreur lors du rejet de la demande d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors du rejet de la demande d'amitié.\"}") .build(); } } /** * Supprime une relation d'amitié. * * @param friendshipId L'ID de la relation d'amitié à supprimer. * @return Confirmation de la suppression. */ @DELETE @Path("/{friendshipId}") @Operation( summary = "Supprimer une relation d'amitié", description = "Supprime une relation d'amitié existante") @APIResponses({ @APIResponse(responseCode = "204", description = "Relation d'amitié supprimée"), @APIResponse(responseCode = "404", description = "Relation d'amitié non trouvée"), @APIResponse( responseCode = "500", description = "Erreur lors de la suppression de la relation d'amitié") }) public Response removeFriend(@PathParam("friendshipId") UUID friendshipId) { logger.info( "[LOG] Reçu une demande pour supprimer la relation d'amitié avec l'ID : " + friendshipId); try { friendshipService.removeFriend(friendshipId); logger.info("[LOG] Relation d'amitié supprimée avec succès."); return Response.noContent().build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la suppression de la relation d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la suppression de la relation d'amitié.\"}") .build(); } } /** * Récupère la liste des amis d'un utilisateur. * * @param userId L'ID de l'utilisateur * @param page Numéro de la page pour la pagination * @param size Nombre d'éléments par page * @return Liste des amis de l'utilisateur avec pagination */ @GET @Path("/list/{userId}") @Operation( summary = "Récupérer la liste des amis", description = "Retourne la liste des amis d'un utilisateur avec pagination") @APIResponses({ @APIResponse( responseCode = "200", description = "Liste des amis récupérée avec succès", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse(responseCode = "500", description = "Erreur lors de la récupération des amis") }) public Response listFriends( @PathParam("userId") UUID userId, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("10") int size) { logger.info("[LOG] Reçu une demande pour récupérer la liste des amis de l'utilisateur avec l'ID : " + userId); try { List friendships = friendshipService.listFriends(userId, page, size) .stream() .distinct() // Assure qu'il n'y a pas de doublons .toList(); logger.info("[LOG] Liste des amis récupérée avec succès, nombre d'amis : " + friendships.size()); return Response.ok(friendships).build(); } catch (UserNotFoundException e) { logger.error("[ERROR] Utilisateur non trouvé : " + e.getMessage()); return Response.status(Response.Status.NOT_FOUND) .entity("{\"message\": \"Utilisateur non trouvé.\"}") .build(); } catch (Exception e) { logger.error("[ERROR] Erreur lors de la récupération de la liste des amis : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des amis.\"}") .build(); } } /** * Récupérer les demandes d'amitié en attente pour un utilisateur. * * @param userId L'ID de l'utilisateur * @param page Numéro de la page pour la pagination * @param size Nombre d'éléments par page * @return Liste des demandes d'amitié en attente */ @GET @Path("/pending/{userId}") @Operation( summary = "Récupérer les demandes d'amitié en attente", description = "Retourne la liste des demandes d'amitié en attente pour un utilisateur") @APIResponses({ @APIResponse( responseCode = "200", description = "Demandes d'amitié récupérées", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadStatusResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse( responseCode = "500", description = "Erreur lors de la récupération des demandes d'amitié") }) public Response getPendingFriendRequests( @PathParam("userId") UUID userId, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("10") int size) { logger.info("[LOG] Récupération des demandes d'amitié en attente pour l'utilisateur : " + userId); try { FriendshipReadStatusRequestDTO request = new FriendshipReadStatusRequestDTO( userId, FriendshipStatus.PENDING, page + 1, size); List friendships = friendshipService.listFriendRequestsByStatus(request); logger.info("[LOG] " + friendships.size() + " demandes d'amitié en attente récupérées avec succès."); return Response.ok(friendships).build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des demandes d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des demandes d'amitié.\"}") .build(); } } /** * 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é. */ @POST @Path("/status") @Operation( summary = "Récupérer les demandes d'amitié par statut", description = "Retourne la liste des demandes d'amitié avec un statut particulier") @APIResponses({ @APIResponse( responseCode = "200", description = "Demandes d'amitié récupérées", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadStatusResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse( responseCode = "500", description = "Erreur lors de la récupération des demandes d'amitié") }) public Response listFriendRequestsByStatus( @Valid @NotNull FriendshipReadStatusRequestDTO request) { logger.info("[LOG] Récupération des demandes d'amitié avec le statut : " + request.getStatus()); try { List friendships = friendshipService.listFriendRequestsByStatus(request); logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées avec succès."); return Response.ok(friendships).build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des demandes d'amitié : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des demandes d'amitié.\"}") .build(); } } /** * 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 pour la pagination. * @param size Nombre d'éléments par page. * @return Liste des demandes d'amitié envoyées. */ @GET @Path("/sent/{userId}") @Operation( summary = "Récupérer les demandes d'amitié envoyées", description = "Retourne la liste des demandes d'amitié envoyées par un utilisateur") @APIResponses({ @APIResponse( responseCode = "200", description = "Demandes d'amitié envoyées récupérées", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadStatusResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse( responseCode = "500", description = "Erreur lors de la récupération des demandes d'amitié envoyées") }) public Response getSentFriendRequests( @PathParam("userId") UUID userId, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("10") int size) { logger.info("[LOG] Récupération des demandes d'amitié envoyées pour l'utilisateur : " + userId); try { List friendships = friendshipService.listSentFriendRequests(userId, page + 1, size); logger.info("[LOG] " + friendships.size() + " demandes d'amitié envoyées récupérées avec succès."); return Response.ok(friendships).build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des demandes d'amitié envoyées : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des demandes d'amitié envoyées.\"}") .build(); } } /** * 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 pour la pagination. * @param size Nombre d'éléments par page. * @return Liste des demandes d'amitié reçues. */ @GET @Path("/received/{userId}") @Operation( summary = "Récupérer les demandes d'amitié reçues", description = "Retourne la liste des demandes d'amitié reçues par un utilisateur") @APIResponses({ @APIResponse( responseCode = "200", description = "Demandes d'amitié reçues récupérées", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadStatusResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse( responseCode = "500", description = "Erreur lors de la récupération des demandes d'amitié reçues") }) public Response getReceivedFriendRequests( @PathParam("userId") UUID userId, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("10") int size) { logger.info("[LOG] Récupération des demandes d'amitié reçues pour l'utilisateur : " + userId); try { List friendships = friendshipService.listReceivedFriendRequests(userId, page + 1, size); logger.info("[LOG] " + friendships.size() + " demandes d'amitié reçues récupérées avec succès."); return Response.ok(friendships).build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des demandes d'amitié reçues : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des demandes d'amitié reçues.\"}") .build(); } } /** * Récupère les détails complets d'un ami. * * @param request DTO contenant l'ID de l'utilisateur et de l'ami dont les détails sont requis. * @return Les détails complets de l'ami. */ @POST @Path("/details") @Operation( summary = "Récupérer les détails d'un ami", description = "Permet de récupérer toutes les informations disponibles sur un ami spécifique") @APIResponses({ @APIResponse( responseCode = "200", description = "Détails de l'ami récupérés avec succès", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))), @APIResponse(responseCode = "404", description = "Ami non trouvé"), @APIResponse(responseCode = "500", description = "Erreur serveur lors de la récupération des détails de l'ami") }) public Response getFriendDetails(@Valid @NotNull FriendshipReadFriendDetailsRequestDTO request) { logger.info( "[LOG] Reçu une demande pour récupérer les détails de l'ami avec l'ID : " + request.getFriendId() + " pour l'utilisateur : " + request.getUserId()); try { // Appel du service pour récupérer les détails de l'ami FriendshipReadFriendDetailsResponseDTO friendDetails = friendshipService.getFriendDetails(request); logger.info( "[LOG] Détails de l'ami récupérés avec succès pour l'utilisateur : " + request.getUserId() + ", ami ID : " + request.getFriendId()); return Response.ok(friendDetails).build(); } catch (NotFoundException e) { logger.warn( "[WARN] Aucun ami trouvé pour l'utilisateur : " + request.getUserId() + " avec l'ID de l'ami : " + request.getFriendId()); return Response.status(Response.Status.NOT_FOUND) .entity("{\"message\": \"Ami non trouvé.\"}") .build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des détails de l'ami : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des détails de l'ami.\"}") .build(); } } /** * Récupérer les suggestions d'amis pour un utilisateur. * * @param userId ID de l'utilisateur. * @param limit Nombre maximum de suggestions (optionnel, par défaut 10). * @return Liste des suggestions d'amis. */ @GET @Path("/suggestions/{userId}") @Operation( summary = "Récupérer les suggestions d'amis", description = "Retourne une liste d'utilisateurs suggérés comme amis potentiels basée sur les amis en commun") @APIResponses({ @APIResponse( responseCode = "200", description = "Suggestions d'amis récupérées", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = com.lions.dev.dto.response.users.FriendSuggestionResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse( responseCode = "500", description = "Erreur lors de la récupération des suggestions d'amis") }) public Response getFriendSuggestions( @PathParam("userId") UUID userId, @QueryParam("limit") @DefaultValue("10") int limit) { logger.info("[LOG] Récupération des suggestions d'amis pour l'utilisateur : " + userId); try { List suggestions = friendshipService.getFriendSuggestions(userId, limit); logger.info("[LOG] " + suggestions.size() + " suggestions d'amis récupérées avec succès."); return Response.ok(suggestions).build(); } catch (UserNotFoundException e) { logger.error("[ERROR] Utilisateur non trouvé : " + e.getMessage()); return Response.status(Response.Status.NOT_FOUND) .entity("{\"message\": \"Utilisateur non trouvé.\"}") .build(); } catch (Exception e) { logger.error( "[ERROR] Erreur lors de la récupération des suggestions d'amis : " + e.getMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("{\"message\": \"Erreur lors de la récupération des suggestions d'amis.\"}") .build(); } } }