package com.gbcm.server.impl.resource; import com.gbcm.server.api.dto.client.ClientDTO; import com.gbcm.server.api.dto.client.CreateClientDTO; import com.gbcm.server.api.dto.client.UpdateClientDTO; import com.gbcm.server.api.dto.common.PagedResponseDTO; import com.gbcm.server.api.enums.ServiceType; import com.gbcm.server.api.exception.GBCMException; import com.gbcm.server.api.service.ClientService; import com.gbcm.server.impl.entity.Client.ClientStatus; 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 org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.Parameter; 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.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Contrôleur REST pour la gestion des clients de la plateforme GBCM. * Expose tous les endpoints CRUD pour les clients avec sécurité basée sur les rôles. * * @author GBCM Development Team * @version 1.0 * @since 1.0 */ @Path("/api/clients") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Tag(name = "Clients", description = "Gestion des clients GBCM") public class ClientResource { private static final Logger logger = LoggerFactory.getLogger(ClientResource.class); @Inject ClientService clientService; /** * Endpoint pour récupérer la liste paginée des clients. * * @param page numéro de page (commence à 0) * @param size taille de page * @param sort critères de tri * @param status filtre par statut * @param industry filtre par secteur d'activité * @param search terme de recherche * @return liste paginée des clients */ @GET @RolesAllowed({"ADMIN", "MANAGER", "COACH"}) @Operation( summary = "Liste des clients", description = "Récupère la liste paginée des clients avec filtres optionnels" ) @APIResponses({ @APIResponse( responseCode = "200", description = "Liste récupérée avec succès", content = @Content(schema = @Schema(implementation = PagedResponseDTO.class)) ), @APIResponse(responseCode = "401", description = "Non authentifié"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Response getClients( @Parameter(description = "Numéro de page (commence à 0)", example = "0") @QueryParam("page") @DefaultValue("0") int page, @Parameter(description = "Taille de page", example = "20") @QueryParam("size") @DefaultValue("20") int size, @Parameter(description = "Tri (ex: companyName,asc ou convertedAt,desc)") @QueryParam("sort") String sort, @Parameter(description = "Filtre par statut") @QueryParam("status") ClientStatus status, @Parameter(description = "Filtre par secteur d'activité") @QueryParam("industry") String industry, @Parameter(description = "Terme de recherche (nom entreprise, email)") @QueryParam("search") String search ) { try { logger.info("Récupération de la liste des clients - page: {}, size: {}", page, size); PagedResponseDTO clients = clientService.getClients(page, size, sort, status, industry, search); logger.info("Liste des clients récupérée avec succès - {} éléments", clients.getTotalElements()); return Response.ok(clients).build(); } catch (GBCMException e) { logger.error("Erreur GBCM lors de la récupération des clients: {}", e.getMessage()); return Response.status(Response.Status.BAD_REQUEST) .entity("Erreur: " + e.getMessage()) .build(); } catch (Exception e) { logger.error("Erreur inattendue lors de la récupération des clients: {}", e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur interne du serveur") .build(); } } /** * Endpoint pour récupérer un client par son ID. * * @param id l'identifiant du client * @return le client trouvé */ @GET @Path("/{id}") @RolesAllowed({"ADMIN", "MANAGER", "COACH", "CLIENT"}) @Operation( summary = "Récupérer un client", description = "Récupère un client par son identifiant" ) @APIResponses({ @APIResponse( responseCode = "200", description = "Client trouvé", content = @Content(schema = @Schema(implementation = ClientDTO.class)) ), @APIResponse(responseCode = "401", description = "Non authentifié"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Client non trouvé"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Response getClientById( @Parameter(description = "Identifiant du client", required = true) @PathParam("id") Long id ) { try { logger.info("Récupération du client avec l'ID: {}", id); ClientDTO client = clientService.getClientById(id); logger.info("Client récupéré avec succès: {}", client.getCompanyName()); return Response.ok(client).build(); } catch (GBCMException e) { logger.warn("Client non trouvé avec l'ID {}: {}", id, e.getMessage()); return Response.status(Response.Status.NOT_FOUND) .entity("Client non trouvé: " + e.getMessage()) .build(); } catch (Exception e) { logger.error("Erreur inattendue lors de la récupération du client {}: {}", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur interne du serveur") .build(); } } /** * Endpoint pour créer un nouveau client. * * @param createClientDTO les données du nouveau client * @return le client créé */ @POST @RolesAllowed({"ADMIN", "MANAGER"}) @Operation( summary = "Créer un client", description = "Crée un nouveau client dans le système" ) @APIResponses({ @APIResponse( responseCode = "201", description = "Client créé avec succès", content = @Content(schema = @Schema(implementation = ClientDTO.class)) ), @APIResponse(responseCode = "400", description = "Données invalides"), @APIResponse(responseCode = "401", description = "Non authentifié"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "409", description = "Client déjà existant"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Response createClient( @Parameter(description = "Données du nouveau client", required = true) @Valid CreateClientDTO createClientDTO ) { try { logger.info("Création d'un nouveau client: {}", createClientDTO.getCompanyName()); ClientDTO client = clientService.createClient(createClientDTO); logger.info("Client créé avec succès avec l'ID: {}", client.getId()); return Response.status(Response.Status.CREATED).entity(client).build(); } catch (GBCMException e) { logger.error("Erreur GBCM lors de la création du client: {}", e.getMessage()); return Response.status(Response.Status.BAD_REQUEST) .entity("Erreur: " + e.getMessage()) .build(); } catch (Exception e) { logger.error("Erreur inattendue lors de la création du client: {}", e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur interne du serveur") .build(); } } /** * Endpoint pour mettre à jour un client existant. * * @param id l'identifiant du client * @param updateClientDTO les données de mise à jour * @return le client mis à jour */ @PUT @Path("/{id}") @RolesAllowed({"ADMIN", "MANAGER", "CLIENT"}) @Operation( summary = "Mettre à jour un client", description = "Met à jour les informations d'un client existant" ) @APIResponses({ @APIResponse( responseCode = "200", description = "Client mis à jour avec succès", content = @Content(schema = @Schema(implementation = ClientDTO.class)) ), @APIResponse(responseCode = "400", description = "Données invalides"), @APIResponse(responseCode = "401", description = "Non authentifié"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Client non trouvé"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Response updateClient( @Parameter(description = "Identifiant du client", required = true) @PathParam("id") Long id, @Parameter(description = "Données de mise à jour", required = true) @Valid UpdateClientDTO updateClientDTO ) { try { logger.info("Mise à jour du client avec l'ID: {}", id); ClientDTO client = clientService.updateClient(id, updateClientDTO); logger.info("Client mis à jour avec succès: {}", client.getCompanyName()); return Response.ok(client).build(); } catch (GBCMException e) { logger.error("Erreur GBCM lors de la mise à jour du client {}: {}", id, e.getMessage()); return Response.status(Response.Status.BAD_REQUEST) .entity("Erreur: " + e.getMessage()) .build(); } catch (Exception e) { logger.error("Erreur inattendue lors de la mise à jour du client {}: {}", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur interne du serveur") .build(); } } /** * Endpoint pour supprimer un client (soft delete). * * @param id l'identifiant du client * @return confirmation de suppression */ @DELETE @Path("/{id}") @RolesAllowed({"ADMIN"}) @Operation( summary = "Supprimer un client", description = "Supprime un client du système (suppression logique)" ) @APIResponses({ @APIResponse(responseCode = "204", description = "Client supprimé avec succès"), @APIResponse(responseCode = "401", description = "Non authentifié"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Client non trouvé"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Response deleteClient( @Parameter(description = "Identifiant du client", required = true) @PathParam("id") Long id ) { try { logger.info("Suppression du client avec l'ID: {}", id); clientService.deleteClient(id); logger.info("Client supprimé avec succès: {}", id); return Response.noContent().build(); } catch (GBCMException e) { logger.error("Erreur GBCM lors de la suppression du client {}: {}", id, e.getMessage()); return Response.status(Response.Status.NOT_FOUND) .entity("Client non trouvé: " + e.getMessage()) .build(); } catch (Exception e) { logger.error("Erreur inattendue lors de la suppression du client {}: {}", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur interne du serveur") .build(); } } }