package dev.lions.unionflow.server.resource; import dev.lions.unionflow.server.api.dto.notification.request.CreateNotificationRequest; import dev.lions.unionflow.server.api.dto.notification.request.CreateTemplateNotificationRequest; import dev.lions.unionflow.server.api.dto.notification.response.NotificationResponse; import dev.lions.unionflow.server.api.dto.notification.response.TemplateNotificationResponse; import dev.lions.unionflow.server.service.NotificationService; import jakarta.annotation.security.RolesAllowed; 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 java.util.List; import java.util.Map; import java.util.UUID; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; import io.quarkus.security.identity.SecurityIdentity; import dev.lions.unionflow.server.repository.MembreRepository; /** * Resource REST pour la gestion des notifications * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Path("/api/notifications") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION", "MODERATEUR", "MEMBRE", "USER" }) @Tag(name = "Notifications", description = "Gestion des notifications : envoi, templates et notifications groupées") public class NotificationResource { private static final Logger LOG = Logger.getLogger(NotificationResource.class); @Inject NotificationService notificationService; @Inject MembreRepository membreRepository; @Inject SecurityIdentity securityIdentity; /** * Notifications du membre connecté (sans passer par membreId). */ @GET @Path("/me") public Response mesNotifications() { try { String email = securityIdentity.getPrincipal().getName(); var membre = membreRepository.findByEmail(email); if (membre.isEmpty()) { return Response.ok(List.of()).build(); } List result = notificationService.listerNotificationsParMembre(membre.get().getId()); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur liste notifications membre connecté"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur: " + e.getMessage())) .build(); } } /** * Notifications non lues du membre connecté. */ @GET @Path("/me/non-lues") public Response mesNotificationsNonLues() { try { String email = securityIdentity.getPrincipal().getName(); var membre = membreRepository.findByEmail(email); if (membre.isEmpty()) { return Response.ok(List.of()).build(); } List result = notificationService.listerNotificationsNonLuesParMembre(membre.get().getId()); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur liste notifications non lues"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur: " + e.getMessage())) .build(); } } // ======================================== // TEMPLATES // ======================================== /** * Crée un nouveau template de notification * * @param templateDTO DTO du template à créer * @return Template créé */ @POST @RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION" }) @Path("/templates") public Response creerTemplate(@Valid CreateTemplateNotificationRequest request) { try { TemplateNotificationResponse result = notificationService.creerTemplate(request); return Response.status(Response.Status.CREATED).entity(result).build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse(e.getMessage())) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la création du template"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur lors de la création du template: " + e.getMessage())) .build(); } } // ======================================== // NOTIFICATIONS // ======================================== /** * Crée une nouvelle notification * * @param notificationDTO DTO de la notification à créer * @return Notification créée */ @POST @RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION" }) public Response creerNotification(@Valid CreateNotificationRequest request) { try { NotificationResponse result = notificationService.creerNotification(request); return Response.status(Response.Status.CREATED).entity(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la création de la notification"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur lors de la création de la notification: " + e.getMessage())) .build(); } } /** * Marque une notification comme lue * * @param id ID de la notification * @return Notification mise à jour */ @POST @RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION", "MODERATEUR", "MEMBRE", "USER" }) @Path("/{id}/marquer-lue") public Response marquerCommeLue(@PathParam("id") UUID id) { try { NotificationResponse result = notificationService.marquerCommeLue(id); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(new ErrorResponse("Notification non trouvée")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors du marquage de la notification"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur lors du marquage de la notification: " + e.getMessage())) .build(); } } /** * Trouve une notification par son ID * * @param id ID de la notification * @return Notification */ @GET @Path("/{id}") public Response trouverNotificationParId(@PathParam("id") UUID id) { try { NotificationResponse result = notificationService.trouverNotificationParId(id); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(new ErrorResponse("Notification non trouvée")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la recherche de la notification"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur lors de la recherche de la notification: " + e.getMessage())) .build(); } } /** * Liste toutes les notifications d'un membre * * @param membreId ID du membre * @return Liste des notifications */ @GET @Path("/membre/{membreId}") public Response listerNotificationsParMembre(@PathParam("membreId") UUID membreId) { try { List result = notificationService.listerNotificationsParMembre(membreId); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la liste des notifications"); return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse("Erreur lors de la liste des notifications: " + e.getMessage())) .build(); } } /** * Liste les notifications non lues d'un membre * * @param membreId ID du membre * @return Liste des notifications non lues */ @GET @Path("/membre/{membreId}/non-lues") public Response listerNotificationsNonLuesParMembre(@PathParam("membreId") UUID membreId) { try { List result = notificationService.listerNotificationsNonLuesParMembre(membreId); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la liste des notifications non lues"); return Response.status(Response.Status.BAD_REQUEST) .entity( new ErrorResponse( "Erreur lors de la liste des notifications non lues: " + e.getMessage())) .build(); } } /** * Liste les notifications en attente d'envoi * * @return Liste des notifications en attente */ @GET @Path("/en-attente-envoi") public Response listerNotificationsEnAttenteEnvoi() { try { List result = notificationService.listerNotificationsEnAttenteEnvoi(); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la liste des notifications en attente"); return Response.status(Response.Status.BAD_REQUEST) .entity( new ErrorResponse( "Erreur lors de la liste des notifications en attente: " + e.getMessage())) .build(); } } /** * Envoie des notifications groupées à plusieurs membres (WOU/DRY) * * @param request DTO contenant les IDs des membres, sujet, corps et canaux * @return Nombre de notifications créées */ @POST @RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION" }) @Path("/groupees") public Response envoyerNotificationsGroupees(NotificationGroupeeRequest request) { try { int notificationsCreees = notificationService.envoyerNotificationsGroupees( request.membreIds, request.sujet, request.corps, request.canaux); return Response.ok(Map.of("notificationsCreees", notificationsCreees)).build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST) .entity(new ErrorResponse(e.getMessage())) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de l'envoi des notifications groupées"); return Response.status(Response.Status.BAD_REQUEST) .entity( new ErrorResponse( "Erreur lors de l'envoi des notifications groupées: " + e.getMessage())) .build(); } } /** Classe interne pour les réponses d'erreur */ public static class ErrorResponse { public String error; public ErrorResponse(String error) { this.error = error; } } /** Classe interne pour les requêtes de notifications groupées (WOU/DRY) */ public static class NotificationGroupeeRequest { public List membreIds; public String sujet; public String corps; public List canaux; public NotificationGroupeeRequest() { } } }