package com.lions.dev.resource; import com.lions.dev.core.errors.exceptions.EventNotFoundException; import com.lions.dev.dto.UserResponseDTO; import com.lions.dev.dto.request.events.EventCreateRequestDTO; import com.lions.dev.dto.request.events.EventReadManyByIdRequestDTO; import com.lions.dev.dto.request.events.EventUpdateRequestDTO; import com.lions.dev.dto.response.comments.CommentResponseDTO; import com.lions.dev.dto.response.events.EventCreateResponseDTO; import com.lions.dev.dto.response.events.EventReadManyByIdResponseDTO; import com.lions.dev.dto.response.events.EventUpdateResponseDTO; import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO; import com.lions.dev.entity.comment.Comment; import com.lions.dev.entity.events.Events; import com.lions.dev.entity.users.Users; import com.lions.dev.repository.EventsRepository; import com.lions.dev.repository.UsersRepository; import com.lions.dev.service.EventService; import com.lions.dev.service.FriendshipService; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; import java.io.File; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; /** * Ressource REST pour la gestion des événements dans le système AfterWork. * Cette classe expose des endpoints pour créer, récupérer, mettre à jour et supprimer des événements. * * Tous les logs nécessaires pour la traçabilité sont intégrés. */ @Path("/events") @Produces("application/json") @Consumes("application/json") @Tag(name = "Events", description = "Opérations liées à la gestion des événements") public class EventsResource { @Inject EventsRepository eventsRepository; @Inject UsersRepository usersRepository; @Inject EventService eventService; @Inject FriendshipService friendshipService; private static final Logger LOG = Logger.getLogger(EventsResource.class); // *********** Création d'un événement *********** @POST @Transactional @Operation(summary = "Créer un nouvel événement", description = "Crée un nouvel événement et retourne ses détails") public Response createEvent(EventCreateRequestDTO eventCreateRequestDTO) { LOG.info("[LOG] Tentative de création d'un nouvel événement : " + eventCreateRequestDTO.getTitle()); Users creator = usersRepository.findById(eventCreateRequestDTO.getCreatorId()); if (creator == null) { LOG.error("[ERROR] Créateur non trouvé avec l'ID : " + eventCreateRequestDTO.getCreatorId()); return Response.status(Response.Status.BAD_REQUEST).entity("Créateur non trouvé").build(); } Events event = eventService.createEvent(eventCreateRequestDTO, creator); LOG.info("[LOG] Événement créé avec succès : " + event.getTitle()); EventCreateResponseDTO responseDTO = new EventCreateResponseDTO(event); return Response.status(Response.Status.CREATED).entity(responseDTO).build(); } // *********** Récupération d'un événement par ID *********** @GET @Path("/{id}") @Operation(summary = "Récupérer un événement par ID", description = "Retourne les détails de l'événement demandé") public Response getEventById(@PathParam("id") UUID id) { LOG.info("[LOG] Récupération de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } EventCreateResponseDTO responseDTO = new EventCreateResponseDTO(event); LOG.info("[LOG] Événement trouvé : " + event.getTitle()); return Response.ok(responseDTO).build(); } // *********** Suppression d'un événement *********** @DELETE @Path("/{id}") @Transactional @Operation(summary = "Supprimer un événement", description = "Supprime un événement de la base de données") public Response deleteEvent(@PathParam("id") UUID id) { LOG.info("Tentative de suppression de l'événement avec l'ID : " + id); try { boolean deleted = eventService.deleteEvent(id); if (deleted) { LOG.info("Événement supprimé avec succès."); return Response.noContent().build(); } else { LOG.warn("Échec de la suppression : événement introuvable avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } } catch (EventNotFoundException e) { LOG.error("[ERROR] Échec de la suppression : " + e.getMessage()); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } } // *********** Ajouter un participant à un événement *********** @POST @Path("/{id}/participants") @Transactional @Operation(summary = "Ajouter un participant à un événement", description = "Ajoute un utilisateur à un événement") public Response addParticipant(@PathParam("id") UUID eventId, Users user) { LOG.info("Ajout d'un participant à l'événement : " + eventId); Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } event.addParticipant(user); eventsRepository.persist(event); LOG.info("Participant ajouté avec succès à l'événement : " + event.getTitle()); return Response.ok(new EventCreateResponseDTO(event)).build(); } // *********** Retirer un participant d'un événement *********** @DELETE @Path("/{id}/participants/{userId}") @Transactional @Operation(summary = "Retirer un participant d'un événement", description = "Supprime un utilisateur de la liste des participants d'un événement") public Response removeParticipant(@PathParam("id") UUID eventId, @PathParam("userId") UUID userId) { LOG.info("Retrait d'un participant de l'événement : " + eventId); Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } Users user = usersRepository.findById(userId); if (user == null) { LOG.warn("Utilisateur non trouvé avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); } event.removeParticipant(user); eventsRepository.persist(event); LOG.info("Participant retiré avec succès de l'événement : " + event.getTitle()); return Response.noContent().build(); } // *********** Mettre à jour un événement *********** @PUT @Path("/{id}") @Transactional @Operation(summary = "Mettre à jour un événement", description = "Modifie un événement existant") public Response updateEvent(@PathParam("id") UUID id, EventUpdateRequestDTO eventUpdateRequestDTO) { LOG.info("[LOG] Tentative de mise à jour de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } // Mise à jour des attributs de l'événement event.setTitle(eventUpdateRequestDTO.getTitle()); event.setStartDate(eventUpdateRequestDTO.getStartDate()); event.setEndDate(eventUpdateRequestDTO.getEndDate()); event.setDescription(eventUpdateRequestDTO.getDescription()); event.setLocation(eventUpdateRequestDTO.getLocation()); event.setCategory(eventUpdateRequestDTO.getCategory()); event.setLink(eventUpdateRequestDTO.getLink()); event.setImageUrl(eventUpdateRequestDTO.getImageUrl()); eventsRepository.persist(event); LOG.info("[LOG] Événement mis à jour avec succès : " + event.getTitle()); EventUpdateResponseDTO responseDTO = new EventUpdateResponseDTO(event); return Response.ok(responseDTO).build(); } // *********** Récupérer les événements créés par un utilisateur spécifique et ses amis *********** @POST @Path("/created-by-user-and-friends") @Consumes("application/json") @Produces("application/json") @Operation(summary = "Récupérer les événements créés par un utilisateur et ses amis", description = "Retourne la liste des événements créés par un utilisateur spécifique et ses amis") public Response getEventsCreatedByUserAndFriends(EventReadManyByIdRequestDTO requestDTO) { UUID userId = requestDTO.getUserId(); LOG.info("[LOG] Récupération des événements pour l'utilisateur avec l'ID : " + userId + " et ses amis"); Users user = usersRepository.findById(userId); if (user == null) { LOG.warn("[LOG] Utilisateur non trouvé avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); } try { List friends = friendshipService.listFriends(userId, 0, Integer.MAX_VALUE); Set friendIds = friends.stream().map(FriendshipReadFriendDetailsResponseDTO::getFriendId).collect(Collectors.toSet()); //friendIds = friendIds.stream().distinct().collect(Collectors.toSet()); LOG.info("[LOG] IDs d'amis + utilisateur (taille attendue: " + friendIds.size() + ") : " + friendIds); if (friendIds.isEmpty()) { LOG.warn("[LOG] Aucun ami trouvé."); return Response.status(Response.Status.NOT_FOUND).entity("Aucun ami trouvé.").build(); } List events = eventsRepository.find("creator.id IN ?1", friendIds).list(); LOG.info("[LOG] Nombre d'événements récupérés dans la requête : " + events.size()); if (events.isEmpty()) { return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé.").build(); } List responseDTOs = events.stream().map(EventReadManyByIdResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } catch (Exception e) { LOG.error("[ERROR] Erreur de récupération des événements : ", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("{\"message\": \"Erreur.\"}").build(); } } // *********** Récupérer les événements par catégorie *********** /** * Endpoint pour récupérer les événements par catégorie. * * @param category La catégorie d'événement à filtrer. * @return Une réponse HTTP contenant la liste des événements dans cette catégorie. */ @GET @Path("/category/{category}") @Operation( summary = "Récupérer les événements par catégorie", description = "Retourne la liste des événements correspondant à une catégorie donnée") public Response getEventsByCategory(@PathParam("category") String category) { LOG.info("[LOG] Récupération des événements dans la catégorie : " + category); List events = eventService.findEventsByCategory(category); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé pour la catégorie : " + category); return Response.status(Response.Status.NOT_FOUND) .entity("Aucun événement trouvé pour cette catégorie.") .build(); } List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés dans la catégorie '" + category + "' : " + events.size()); return Response.ok(responseDTOs).build(); } // *********** Récupérer les événements entre deux dates *********** /** * Endpoint pour récupérer les événements entre deux dates spécifiques. * * @param startDate La date de début pour filtrer les événements. * @param endDate La date de fin pour filtrer les événements. * @return Une réponse HTTP contenant la liste des événements entre les deux dates. */ @GET @Path("/between-dates") @Operation( summary = "Récupérer les événements entre deux dates", description = "Retourne la liste des événements qui se déroulent entre deux dates spécifiques") public Response findEventsBetweenDates( @QueryParam("startDate") LocalDateTime startDate, @QueryParam("endDate") LocalDateTime endDate) { LOG.info("[LOG] Récupération des événements entre les dates : " + startDate + " et " + endDate); if (startDate == null || endDate == null || endDate.isBefore(startDate)) { LOG.error("[ERROR] Les dates fournies sont invalides."); return Response.status(Response.Status.BAD_REQUEST) .entity("Les dates sont invalides ou mal formatées.") .build(); } List events = eventService.findEventsBetweenDates(startDate, endDate); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé entre les dates : " + startDate + " et " + endDate); return Response.status(Response.Status.NOT_FOUND) .entity("Aucun événement trouvé entre ces dates.") .build(); } List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés entre les dates : " + events.size()); return Response.ok(responseDTOs).build(); } // *********** Récupérer les événements par statut *********** /** * Endpoint pour récupérer les événements par statut. * * @param status Le statut des événements à filtrer (en cours, terminé, etc.). * @return Une réponse HTTP contenant la liste des événements avec ce statut. */ @GET @Path("/status/{status}") @Operation( summary = "Récupérer les événements par statut", description = "Retourne la liste des événements correspondant à un statut spécifique") public Response getEventsByStatus(@PathParam("status") String status) { LOG.info("[LOG] Récupération des événements avec le statut : " + status); List events = eventService.findEventsByStatus(status); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé avec le statut : " + status); return Response.status(Response.Status.NOT_FOUND) .entity("Aucun événement trouvé pour ce statut.") .build(); } List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés avec le statut '" + status + "' : " + events.size()); return Response.ok(responseDTOs).build(); } // *********** Rechercher des événements par mots-clés *********** /** * Endpoint pour rechercher des événements par mots-clés. * * @param keyword Le mot-clé à rechercher. * @return Une réponse HTTP contenant la liste des événements correspondant au mot-clé. */ @GET @Path("/search") @Operation( summary = "Rechercher des événements par mots-clés", description = "Retourne la liste des événements dont le titre ou la description contient les mots-clés spécifiés") public Response searchEvents(@QueryParam("keyword") String keyword) { LOG.info("[LOG] Recherche d'événements avec le mot-clé : " + keyword); List events = eventService.searchEvents(keyword); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé avec le mot-clé : " + keyword); return Response.status(Response.Status.NOT_FOUND) .entity("Aucun événement trouvé pour ce mot-clé.") .build(); } List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés avec le mot-clé '" + keyword + "' : " + events.size()); return Response.ok(responseDTOs).build(); } // *********** Mettre à jour le statut d'un événement *********** /** * Endpoint pour mettre à jour le statut d'un événement. * * @param id L'ID de l'événement. * @param status Le nouveau statut de l'événement. * @return Une réponse HTTP indiquant la mise à jour du statut. */ @PUT @Path("/{id}/status") @Transactional @Operation( summary = "Mettre à jour le statut d'un événement", description = "Modifie le statut d'un événement (ouvert, fermé, annulé, etc.)") public Response updateEventStatus(@PathParam("id") UUID id, @QueryParam("status") String status) { LOG.info("[LOG] Mise à jour du statut de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } event.setStatus(status); eventsRepository.persist(event); LOG.info("[LOG] Statut de l'événement mis à jour avec succès : " + status); EventUpdateResponseDTO responseDTO = new EventUpdateResponseDTO(event); return Response.ok(responseDTO).build(); } // *********** Récupérer les événements auxquels un utilisateur est inscrit *********** /** * Endpoint pour récupérer les événements auxquels un utilisateur est inscrit. * * @param userId L'ID de l'utilisateur. * @return Une réponse HTTP contenant la liste des événements. */ @GET @Path("/user/{userId}") @Operation( summary = "Récupérer les événements auxquels un utilisateur est inscrit", description = "Retourne la liste des événements auxquels un utilisateur spécifique est inscrit") public Response getEventsByUser(@PathParam("userId") UUID userId) { LOG.info("[LOG] Récupération des événements pour l'utilisateur avec l'ID : " + userId); Users user = usersRepository.findById(userId); if (user == null) { LOG.warn("[LOG] Utilisateur non trouvé avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); } List events = eventService.findEventsByUser(user); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé pour l'utilisateur avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé.").build(); } List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés pour l'utilisateur : " + events.size()); return Response.ok(responseDTOs).build(); } // *********** Mettre à jour l'image d'un événement *********** /** * Endpoint pour mettre à jour l'image d'un événement. * * @param id L'identifiant de l'événement. * @param imageFilePath Le chemin vers l'image de l'événement. * @return Un message indiquant si la mise à jour a réussi ou non. */ @PUT @Path("/{id}/image") public Response updateEventImage(@PathParam("id") UUID id, String imageFilePath) { LOG.info("[LOG] Tentative de mise à jour de l'image pour l'événement avec l'ID : " + id); try { if (imageFilePath == null || imageFilePath.isEmpty()) { LOG.error("[ERROR] Le chemin de l'image est vide ou null."); return Response.status(Response.Status.BAD_REQUEST).entity("Le chemin de l'image est vide ou null.").build(); } File file = new File(imageFilePath); if (!file.exists()) { LOG.error("[ERROR] Le fichier spécifié n'existe pas : " + imageFilePath); return Response.status(Response.Status.NOT_FOUND).entity("Le fichier spécifié n'existe pas.").build(); } Events event = eventService.getEventById(id); if (event == null) { LOG.error("[ERROR] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } String imageUrl = file.getAbsolutePath(); event.setImageUrl(imageUrl); eventService.updateEvent(event); LOG.info("[LOG] Image de l'événement mise à jour avec succès pour : " + event.getTitle()); return Response.ok("Image de l'événement mise à jour avec succès.").build(); } catch (Exception e) { LOG.error("[ERROR] Erreur lors de la mise à jour de l'image de l'événement : ", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Erreur lors de la mise à jour de l'image de l'événement.").build(); } } // *********** Mettre à jour partiellement un événement *********** @PATCH @Path("/{id}/partial-update") @Transactional @Operation(summary = "Mettre à jour partiellement un événement", description = "Mise à jour partielle des informations d'un événement") public Response partialUpdateEvent(@PathParam("id") UUID id, Map updates) { LOG.info("[LOG] Tentative de mise à jour partielle de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } updates.forEach((field, value) -> { // Mise à jour des champs dynamiquement, à adapter selon la structure de l'événement // Exemple d'utilisation de réflexion si applicable }); eventsRepository.persist(event); LOG.info("[LOG] Événement mis à jour partiellement avec succès : " + event.getTitle()); return Response.ok(new EventUpdateResponseDTO(event)).build(); } // *********** Récupérer les événements à venir *********** @GET @Path("/upcoming") @Operation(summary = "Récupérer les événements à venir", description = "Retourne les événements futurs.") public Response getUpcomingEvents() { LOG.info("[LOG] Récupération des événements à venir."); List events = eventService.findUpcomingEvents(); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement futur trouvé."); return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement futur trouvé.").build(); } List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } // *********** Récupérer les événements passés *********** @GET @Path("/past") @Operation(summary = "Récupérer les événements passés", description = "Retourne les événements déjà terminés.") public Response getPastEvents() { LOG.info("[LOG] Récupération des événements passés."); List events = eventService.findPastEvents(); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement passé trouvé."); return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement passé trouvé.").build(); } List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } // *********** Annuler un événement *********** @POST @Path("/{id}/cancel") @Transactional @Operation(summary = "Annuler un événement", description = "Annule un événement sans le supprimer.") public Response cancelEvent(@PathParam("id") UUID id) { LOG.info("[LOG] Annulation de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } event.setStatus("Annulé"); eventsRepository.persist(event); LOG.info("[LOG] Événement annulé avec succès : " + event.getTitle()); return Response.ok(new EventUpdateResponseDTO(event)).build(); } // *********** Récupérer les événements par localisation *********** @GET @Path("/location/{location}") @Operation(summary = "Récupérer les événements par localisation", description = "Retourne les événements situés à une localisation spécifique.") public Response getEventsByLocation(@PathParam("location") String location) { LOG.info("[LOG] Récupération des événements à la localisation : " + location); List events = eventService.findEventsByLocation(location); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé pour la localisation : " + location); return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé pour cette localisation.").build(); } List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } // *********** Récupérer les événements populaires *********** @GET @Path("/popular") @Operation(summary = "Récupérer les événements populaires", description = "Retourne les événements ayant le plus de participants.") public Response getPopularEvents() { LOG.info("[LOG] Récupération des événements populaires."); List events = eventService.findPopularEvents(); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement populaire trouvé."); return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement populaire trouvé.").build(); } List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } // *********** Étendre la durée d'un événement *********** @PATCH @Path("/{id}/extend") @Transactional @Operation(summary = "Étendre la durée d'un événement", description = "Permet de modifier la date de fin d'un événement.") public Response extendEventDuration(@PathParam("id") UUID id, LocalDateTime newEndDate) { LOG.info("[LOG] Extension de la durée de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } if (newEndDate.isBefore(event.getStartDate())) { LOG.error("[ERROR] La nouvelle date de fin est antérieure à la date de début."); return Response.status(Response.Status.BAD_REQUEST).entity("La nouvelle date de fin doit être postérieure à la date de début.").build(); } event.setEndDate(newEndDate); eventsRepository.persist(event); LOG.info("[LOG] Durée de l'événement étendue avec succès : " + event.getTitle()); return Response.ok(new EventUpdateResponseDTO(event)).build(); } // *********** Inviter des utilisateurs à un événement *********** @POST @Path("/{id}/invite") @Transactional @Operation(summary = "Inviter des utilisateurs à un événement", description = "Envoie des invitations à des utilisateurs pour un événement.") public Response inviteUsersToEvent(@PathParam("id") UUID eventId, Set userIds) { LOG.info("[LOG] Invitation d'utilisateurs à l'événement : " + eventId); Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } List invitedUsers = userIds.stream().map(usersRepository::findById).filter(u -> u != null).collect(Collectors.toList()); invitedUsers.forEach(event::addParticipant); // Adapte pour ajouter en tant qu'invités, si nécessaire eventsRepository.persist(event); LOG.info("[LOG] Utilisateurs invités avec succès à l'événement : " + event.getTitle()); return Response.ok("Invitations envoyées avec succès.").build(); } @GET @Path("/{id}/participants") @Operation(summary = "Récupérer la liste des participants d'un événement", description = "Retourne la liste des utilisateurs participant à un événement spécifique.") public Response getParticipants(@PathParam("id") UUID eventId) { // Log d'entrée de la méthode LOG.info("[LOG] Récupération des participants de l'événement avec l'ID : " + eventId); // Recherche de l'événement Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } // Récupération de la liste des participants Set participantsSet = event.getParticipants(); if (participantsSet == null || participantsSet.isEmpty()) { LOG.warn("[LOG] Aucun participant trouvé pour l'événement avec l'ID : " + eventId); return Response.status(Response.Status.NO_CONTENT).entity("Aucun participant trouvé.").build(); } // Conversion des participants en List List participantsList = new ArrayList<>(participantsSet); // Conversion des participants en DTO pour la réponse List responseDTOs = participantsList.stream() .map(UserResponseDTO::new) // Conversion de chaque utilisateur en UserResponseDTO .collect(Collectors.toList()); // Log de la taille de la liste des participants pour la traçabilité LOG.info("[LOG] Nombre de participants récupérés pour l'événement avec l'ID : " + eventId + " : " + responseDTOs.size()); // Retourner la réponse avec les participants return Response.ok(responseDTOs).build(); } @POST @Path("/{id}/favorite") @Transactional @Operation(summary = "Marquer un événement comme favori", description = "Permet à un utilisateur de marquer un événement comme favori.") public Response favoriteEvent(@PathParam("id") UUID eventId, @QueryParam("userId") UUID userId) { LOG.info("[LOG] Marquage de l'événement comme favori pour l'utilisateur ID : " + userId); Events event = eventsRepository.findById(eventId); Users user = usersRepository.findById(userId); if (event == null || user == null) { LOG.warn("[LOG] Événement ou utilisateur non trouvé."); return Response.status(Response.Status.NOT_FOUND).entity("Événement ou utilisateur non trouvé.").build(); } user.addFavoriteEvent(event); usersRepository.persist(user); return Response.ok("Événement marqué comme favori.").build(); } @GET @Path("/user/{userId}/favorites") @Operation(summary = "Récupérer les événements favoris d'un utilisateur", description = "Retourne les événements marqués comme favoris par un utilisateur.") public Response getFavoriteEvents(@PathParam("userId") UUID userId) { LOG.info("[LOG] Récupération des événements favoris pour l'utilisateur ID : " + userId); Users user = usersRepository.findById(userId); if (user == null) { LOG.warn("[LOG] Utilisateur non trouvé avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); } // Convertir Set en List List favoriteEvents = new ArrayList<>(user.getFavoriteEvents()); // Mapper les événements en DTO List responseDTOs = favoriteEvents.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } @GET @Path("/{id}/comments") @Operation(summary = "Récupérer les commentaires d'un événement", description = "Retourne la liste des commentaires associés à un événement.") public Response getComments(@PathParam("id") UUID eventId) { LOG.info("[LOG] Récupération des commentaires pour l'événement ID : " + eventId); // Recherche de l'événement Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } // Récupération des commentaires associés à l'événement List comments = event.getComments(); List responseDTOs = comments.stream() .map(CommentResponseDTO::new) // Conversion de chaque commentaire en CommentResponseDTO .collect(Collectors.toList()); LOG.info("[LOG] Nombre de commentaires récupérés pour l'événement avec l'ID : " + eventId + " : " + responseDTOs.size()); // Retourner la réponse avec les commentaires sous forme de DTO return Response.ok(responseDTOs).build(); } @GET @Path("/recommendations/{userId}") @Operation(summary = "Recommander des événements basés sur les intérêts", description = "Retourne une liste d'événements recommandés pour un utilisateur.") public Response getEventRecommendations(@PathParam("userId") UUID userId) { LOG.info("[LOG] Récupération des recommandations d'événements pour l'utilisateur ID : " + userId); Users user = usersRepository.findById(userId); if (user == null) { LOG.warn("[LOG] Utilisateur non trouvé avec l'ID : " + userId); return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); } List recommendedEvents = eventService.recommendEventsForUser(user); List responseDTOs = recommendedEvents.stream().map(EventCreateResponseDTO::new).toList(); return Response.ok(responseDTOs).build(); } @GET @Path("/{id}/share-link") @Operation(summary = "Partager un événement via un lien", description = "Génère un lien de partage pour un événement.") public Response getShareLink(@PathParam("id") UUID eventId) { LOG.info("[LOG] Génération du lien de partage pour l'événement ID : " + eventId); Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("[LOG] Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } String shareLink = "https://lions.dev /events/" + eventId; return Response.ok(Map.of("shareLink", shareLink)).build(); } /** * Endpoint pour fermer un événement. * * @param eventId L'ID de l'événement. * @return Une réponse HTTP indiquant le succès de la fermeture. */ @PATCH @Path("/{id}/close") @Transactional @Operation( summary = "Fermer un événement", description = "Ferme un événement et empêche les nouvelles participations" ) public Response closeEvent(@PathParam("id") UUID eventId) { LOG.info("Tentative de fermeture de l'événement avec l'ID : " + eventId); // Recherche de l'événement par ID Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND) .entity("Événement non trouvé.") .build(); } // Marquer l'événement comme fermé event.setStatus("fermé"); // Modification du statut de l'événement eventsRepository.persist(event); // Persister les modifications dans la base LOG.info("Événement fermé avec succès : " + event.getTitle()); // Retourner une réponse HTTP 200 OK avec le DTO de l'événement fermé return Response.ok(new EventCreateResponseDTO(event)).build(); } /** * Endpoint pour réouvrir un événement. * * @param eventId L'ID de l'événement à rouvrir. * @return Une réponse HTTP indiquant le succès ou l'échec de la réouverture. */ @PATCH @Path("{eventId}/reopen") @Transactional @Operation( summary = "Rouvrir un événement", description = "Rouvre un événement existant qui est actuellement fermé" ) public Response reopenEvent(@PathParam("eventId") UUID eventId) { LOG.info("Tentative de réouverture de l'événement avec l'ID : " + eventId); // Recherche de l'événement par ID Events event = eventsRepository.findById(eventId); if (event == null) { LOG.warn("Événement non trouvé avec l'ID : " + eventId); return Response.status(Response.Status.NOT_FOUND) .entity("Événement non trouvé.") .build(); } // Vérifier si l'événement est déjà ouvert if ("ouvert".equals(event.getStatus())) { LOG.warn("L'événement est déjà ouvert : " + eventId); return Response.status(Response.Status.BAD_REQUEST) .entity("L'événement est déjà ouvert.") .build(); } // Vérifier si l'événement est fermé avant de tenter la réouverture if (!"fermé".equals(event.getStatus())) { LOG.warn("L'événement n'est pas fermé, donc il ne peut pas être rouvert : " + eventId); return Response.status(Response.Status.BAD_REQUEST) .entity("L'événement n'est pas fermé et ne peut pas être rouvert.") .build(); } // Réouvrir l'événement en mettant à jour son statut event.setStatus("ouvert"); // Changer le statut à "Ouvert" eventsRepository.persist(event); // Persister les modifications dans la base LOG.info("Événement rouvert avec succès : " + event.getTitle()); // Retourner une réponse HTTP 200 OK avec un message de succès return Response.ok("L'événement a été réouvert avec succès.").build(); } }