package com.lions.dev.resource; import com.lions.dev.service.EventService; import com.lions.dev.repository.EventsRepository; import com.lions.dev.dto.request.events.EventCreateRequestDTO; import com.lions.dev.dto.request.events.EventUpdateRequestDTO; import com.lions.dev.dto.response.events.EventCreateResponseDTO; import com.lions.dev.dto.response.events.EventUpdateResponseDTO; import com.lions.dev.entity.events.Events; import com.lions.dev.entity.users.Users; import com.lions.dev.repository.UsersRepository; // Ajout du UsersRepository pour gérer les import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; import java.io.File; // participants import java.time.LocalDateTime; import java.util.List; import java.util.UUID; import com.lions.dev.core.errors.exceptions.EventNotFoundException; 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, 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; // Ajout pour la gestion des participants @Inject EventService eventService; private static final Logger LOG = Logger.getLogger(EventsResource.class); /** * Endpoint pour créer un nouvel événement. * * @param eventCreateRequestDTO Le DTO contenant les informations de l'événement à créer. * @return Une réponse HTTP contenant l'événement créé ou un message d'erreur. */ @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()); // Récupérer l'utilisateur créateur à partir de l'identifiant 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(); } // Appel au service pour créer l'événement 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(); } /** * Endpoint pour récupérer les détails d'un événement par ID. * * @param id L'ID de l'événement. * @return Une réponse HTTP contenant les informations de l'événement. */ @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(); } /** * Endpoint pour récupérer une liste de tous les événements après une date donnée. * * @param startDate La date de début à partir de laquelle filtrer les événements. * @return Une réponse HTTP contenant la liste des événements après cette date. */ @GET @Path("/after-date") @Operation( summary = "Récupérer les événements après une date", description = "Retourne les événements après une date donnée") public Response getEventsAfterDate(@QueryParam("startDate") LocalDateTime startDate) { LOG.info("[LOG] Récupération des événements après la date : " + startDate); // Appel au service pour récupérer les événements après une date donnée List events = eventService.getEventsAfterDate(startDate); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé après la date : " + startDate); return Response.status(Response.Status.NOT_FOUND) .entity("Aucun événement trouvé après cette date.") .build(); } // Transformer la liste des événements en DTO pour la réponse List responseDTOs = events.stream() .map(EventCreateResponseDTO::new) .toList(); LOG.info("[LOG] Nombre d'événements trouvés après la date : " + events.size()); return Response.ok(responseDTOs).build(); } /** * Endpoint pour supprimer un événement par ID. * * @param id L'ID de l'événement à supprimer. * @return Une réponse HTTP indiquant le succès ou l'échec de la suppression. */ @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); // Appel du service pour la suppression de l'événement 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(); } } /** * Endpoint pour ajouter un participant à un événement. * * @param eventId L'ID de l'événement. * @param user L'utilisateur à ajouter comme participant. * @return Une réponse HTTP indiquant le succès de l'ajout. */ @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(); } /** * Endpoint pour retirer un participant d'un événement. * * @param eventId L'ID de l'événement. * @param userId L'ID de l'utilisateur à retirer. * @return Une réponse HTTP indiquant le succès du retrait. */ @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(); } /** * Endpoint pour obtenir le nombre de participants à un événement. * * @param eventId L'ID de l'événement. * @return Le nombre de participants. */ @GET @Path("/{id}/participants/count") @Operation( summary = "Obtenir le nombre de participants à un événement", description = "Retourne le nombre total de participants à un événement") public Response getNumberOfParticipants(@PathParam("id") UUID eventId) { LOG.info("Récupération du nombre de participants pour 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(); } int participantCount = event.getNumberOfParticipants(); LOG.info("Nombre de participants pour l'événement : " + participantCount); return Response.ok(participantCount).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. */ @POST @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); 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.setClosed(true); // Marquer l'événement comme fermé eventsRepository.persist(event); LOG.info("Événement fermé avec succès : " + event.getTitle()); return Response.ok(new EventCreateResponseDTO(event)).build(); } /** * Endpoint pour mettre à jour un événement. * * @param id L'ID de l'événement. * @param eventUpdateRequestDTO Le DTO de la requête de mise à jour. * @return Une réponse HTTP indiquant la mise à jour. */ @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(); } /** * 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 @jakarta.ws.rs.Path("/{id}/image") public String updateEventImage(@PathParam("id") UUID id, String imageFilePath) { try { // Vérification si le chemin d'image est vide ou null if (imageFilePath == null || imageFilePath.isEmpty()) { System.out.println("[ERROR] Le chemin de l'image est vide ou null."); return "Le chemin de l'image est vide ou null."; } // Utiliser File pour vérifier si le fichier existe File file = new File(imageFilePath); if (!file.exists()) { System.out.println("[ERROR] Le fichier spécifié n'existe pas : " + imageFilePath); return "Le fichier spécifié n'existe pas."; } // Récupérer l'événement par son ID Events event = eventService.getEventById(id); if (event == null) { System.out.println("[ERROR] Événement non trouvé avec l'ID : " + id); return "Événement non trouvé."; } // Mettre à jour l'URL de l'image de l'événement String imageUrl = file.getAbsolutePath(); // Obtenir le chemin complet du fichier event.setImageUrl(imageUrl); // Mise à jour de l'événement eventService.updateEvent(event); System.out.println( "[LOG] Image de l'événement mise à jour avec succès pour : " + event.getTitle()); return "Image de l'événement mise à jour avec succès."; } catch (Exception e) { System.out.println( "[ERROR] Erreur lors de la mise à jour de l'image de l'événement : " + e.getMessage()); return "Erreur lors de la mise à jour de l'image de l'événement."; } } /** * Endpoint pour récupérer la liste de tous les événements. * * @return Une réponse HTTP contenant la liste des événements. */ @GET @Operation( summary = "Récupérer tous les événements", description = "Retourne la liste de tous les événements disponibles") public Response getAllEvents() { LOG.info("[LOG] Récupération de tous les événements disponibles"); List events = eventsRepository.findAll().list(); if (events.isEmpty()) { LOG.warn("[LOG] Aucun événement trouvé."); 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 total d'événements trouvés : " + events.size()); return Response.ok(responseDTOs).build(); } /** * 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(); } /** * 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(); } /** * 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(); } /** * 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(); } /** * 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(); } /** * 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); // Vérification de la validité des dates 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(); } // Appel au service pour récupérer les événements entre les dates données 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(); } // Transformation des événements en DTO pour la réponse 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(); } }