package com.lions.dev.resource; import com.lions.dev.dto.request.chat.SendMessageRequestDTO; import com.lions.dev.dto.response.chat.ConversationResponseDTO; import com.lions.dev.dto.response.chat.MessageResponseDTO; import com.lions.dev.entity.chat.Conversation; import com.lions.dev.entity.chat.Message; import com.lions.dev.entity.users.Users; import com.lions.dev.service.MessageService; import com.lions.dev.service.UsersService; import jakarta.inject.Inject; import jakarta.validation.Valid; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; /** * Resource REST pour la gestion des messages et conversations. * * Cette classe expose les endpoints HTTP pour: * - Envoyer des messages * - Récupérer les conversations * - Récupérer les messages d'une conversation * - Marquer les messages comme lus * - Supprimer des messages et conversations * * La couche resource ne fait pas d'accès direct au repository : elle délègue au service * et laisse le GlobalExceptionHandler gérer les exceptions métier. */ @Path("/messages") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Tag(name = "Messages", description = "Gestion des messages et conversations") public class MessageResource { private static final Logger LOG = Logger.getLogger(MessageResource.class); @Inject MessageService messageService; @Inject UsersService usersService; @POST @Operation(summary = "Envoyer un message", description = "Envoie un nouveau message à un utilisateur") public Response sendMessage(@Valid SendMessageRequestDTO request) { LOG.info("[LOG] Réception d'une demande d'envoi de message"); Message message = messageService.sendMessage( request.getSenderId(), request.getRecipientId(), request.getContent(), request.getMessageType(), request.getMediaUrl() ); MessageResponseDTO response = new MessageResponseDTO(message); return Response.status(Response.Status.CREATED).entity(response).build(); } @GET @Path("/conversations/{userId}") @Operation(summary = "Récupérer les conversations", description = "Récupère toutes les conversations d'un utilisateur") public Response getUserConversations(@PathParam("userId") UUID userId) { LOG.info("[LOG] Récupération des conversations pour l'utilisateur ID : " + userId); Users user = usersService.getUserById(userId); List conversations = messageService.getUserConversations(userId); List response = conversations.stream() .map(conv -> new ConversationResponseDTO(conv, user)) .collect(Collectors.toList()); return Response.ok(response).build(); } @GET @Path("/conversation/{conversationId}") @Operation(summary = "Récupérer les messages", description = "Récupère les messages d'une conversation avec pagination") public Response getConversationMessages( @PathParam("conversationId") UUID conversationId, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("50") int size) { LOG.info("[LOG] Récupération des messages pour la conversation ID : " + conversationId); List messages = messageService.getConversationMessages(conversationId, page, size); List response = messages.stream() .map(MessageResponseDTO::new) .collect(Collectors.toList()); return Response.ok(response).build(); } @GET @Path("/conversation/between/{user1Id}/{user2Id}") @Operation(summary = "Récupérer une conversation", description = "Récupère la conversation entre deux utilisateurs") public Response getConversationBetweenUsers( @PathParam("user1Id") UUID user1Id, @PathParam("user2Id") UUID user2Id) { LOG.info("[LOG] Recherche de conversation entre " + user1Id + " et " + user2Id); Users user1 = usersService.getUserById(user1Id); Conversation conversation = messageService.getConversationBetweenUsers(user1Id, user2Id); ConversationResponseDTO response = new ConversationResponseDTO(conversation, user1); return Response.ok(response).build(); } @PUT @Path("/{messageId}/read") @Operation(summary = "Marquer comme lu", description = "Marque un message comme lu") public Response markMessageAsRead(@PathParam("messageId") UUID messageId) { LOG.info("[LOG] Marquage du message comme lu : " + messageId); Message message = messageService.markMessageAsRead(messageId); MessageResponseDTO response = new MessageResponseDTO(message); return Response.ok(response).build(); } @PUT @Path("/conversation/{conversationId}/read/{userId}") @Operation(summary = "Marquer tout comme lu", description = "Marque tous les messages d'une conversation comme lus") public Response markAllMessagesAsRead( @PathParam("conversationId") UUID conversationId, @PathParam("userId") UUID userId) { LOG.info("[LOG] Marquage de tous les messages comme lus pour la conversation " + conversationId); int count = messageService.markAllMessagesAsRead(conversationId, userId); return Response.ok("{\"messagesMarkedAsRead\": " + count + "}").build(); } @GET @Path("/unread/count/{userId}") @Operation(summary = "Compter les non lus", description = "Compte le nombre total de messages non lus") public Response getTotalUnreadCount(@PathParam("userId") UUID userId) { LOG.info("[LOG] Récupération du nombre de messages non lus pour l'utilisateur " + userId); long count = messageService.getTotalUnreadCount(userId); return Response.ok("{\"unreadCount\": " + count + "}").build(); } @DELETE @Path("/{messageId}") @Operation(summary = "Supprimer un message", description = "Supprime un message") public Response deleteMessage(@PathParam("messageId") UUID messageId) { LOG.info("[LOG] Suppression du message ID : " + messageId); boolean deleted = messageService.deleteMessage(messageId); if (deleted) { return Response.ok("{\"message\": \"Message supprimé avec succès\"}").build(); } else { return Response.status(Response.Status.NOT_FOUND) .entity("{\"message\": \"Message non trouvé\"}") .build(); } } @DELETE @Path("/conversation/{conversationId}") @Operation(summary = "Supprimer une conversation", description = "Supprime une conversation et tous ses messages") public Response deleteConversation(@PathParam("conversationId") UUID conversationId) { LOG.info("[LOG] Suppression de la conversation ID : " + conversationId); boolean deleted = messageService.deleteConversation(conversationId); if (deleted) { return Response.ok("{\"message\": \"Conversation supprimée avec succès\"}").build(); } else { return Response.status(Response.Status.NOT_FOUND) .entity("{\"message\": \"Conversation non trouvée\"}") .build(); } } }