package dev.lions.btpxpress.adapter.http; import dev.lions.btpxpress.application.service.ClientService; import dev.lions.btpxpress.domain.core.entity.Client; import dev.lions.btpxpress.domain.core.entity.Permission; import dev.lions.btpxpress.domain.shared.dto.ClientCreateDTO; import dev.lions.btpxpress.infrastructure.security.RequirePermission; import io.quarkus.security.Authenticated; import jakarta.inject.Inject; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.UUID; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Resource REST pour la gestion des clients - Architecture 2025 MIGRATION: Préservation exacte de * toutes les API endpoints et contrats */ @Path("/api/v1/clients") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Tag(name = "Clients", description = "Gestion des clients") // @Authenticated - Désactivé pour les tests public class ClientResource { private static final Logger logger = LoggerFactory.getLogger(ClientResource.class); @Inject ClientService clientService; // === ENDPOINTS DE LECTURE - API CONTRACTS PRÉSERVÉS EXACTEMENT === @GET @RequirePermission(Permission.CLIENTS_READ) @Operation(summary = "Récupérer tous les clients") @APIResponse(responseCode = "200", description = "Liste des clients récupérée avec succès") public Response getAllClients( @Parameter(description = "Numéro de page (0-based)") @QueryParam("page") @DefaultValue("0") int page, @Parameter(description = "Taille de la page") @QueryParam("size") @DefaultValue("20") int size) { logger.debug("GET /clients - page: {}, size: {}", page, size); List clients; if (page == 0 && size == 20) { clients = clientService.findAll(); } else { clients = clientService.findAll(page, size); } return Response.ok(clients).build(); } @GET @Path("/{id}") @RequirePermission(Permission.CLIENTS_READ) @Operation(summary = "Récupérer un client par ID") @APIResponse(responseCode = "200", description = "Client trouvé") @APIResponse(responseCode = "404", description = "Client non trouvé") public Response getClientById(@Parameter(description = "ID du client") @PathParam("id") UUID id) { logger.debug("GET /clients/{}", id); Client client = clientService.findByIdRequired(id); return Response.ok(client).build(); } @GET @Path("/search") @Operation(summary = "Rechercher des clients") @APIResponse(responseCode = "200", description = "Résultats de recherche") public Response searchClients( @Parameter(description = "Nom du client") @QueryParam("nom") String nom, @Parameter(description = "Entreprise") @QueryParam("entreprise") String entreprise, @Parameter(description = "Ville") @QueryParam("ville") String ville, @Parameter(description = "Email") @QueryParam("email") String email) { logger.debug( "GET /clients/search - nom: {}, entreprise: {}, ville: {}, email: {}", nom, entreprise, ville, email); List clients; // Logique de recherche exacte préservée if (email != null && !email.trim().isEmpty()) { clients = clientService.findByEmail(email).map(List::of).orElse(List.of()); } else if (nom != null && !nom.trim().isEmpty()) { clients = clientService.searchByNom(nom); } else if (entreprise != null && !entreprise.trim().isEmpty()) { clients = clientService.searchByEntreprise(entreprise); } else if (ville != null && !ville.trim().isEmpty()) { clients = clientService.searchByVille(ville); } else { clients = clientService.findAll(); } return Response.ok(clients).build(); } // === ENDPOINTS D'ÉCRITURE - API CONTRACTS PRÉSERVÉS EXACTEMENT === @POST @RequirePermission(Permission.CLIENTS_CREATE) @Operation(summary = "Créer un nouveau client") @APIResponse(responseCode = "201", description = "Client créé avec succès") @APIResponse(responseCode = "400", description = "Données invalides") public Response createClient(@Valid @NotNull ClientCreateDTO clientDTO) { logger.debug("POST /clients"); logger.info( "Données reçues: nom={}, prenom={}, email={}", clientDTO.getNom(), clientDTO.getPrenom(), clientDTO.getEmail()); try { Client createdClient = clientService.createFromDTO(clientDTO); return Response.status(Response.Status.CREATED).entity(createdClient).build(); } catch (Exception e) { logger.error("Erreur lors de la création du client: {}", e.getMessage(), e); throw e; } } @PUT @Path("/{id}") @RequirePermission(Permission.CLIENTS_UPDATE) @Operation(summary = "Mettre à jour un client") @APIResponse(responseCode = "200", description = "Client mis à jour avec succès") @APIResponse(responseCode = "404", description = "Client non trouvé") @APIResponse(responseCode = "400", description = "Données invalides") public Response updateClient( @Parameter(description = "ID du client") @PathParam("id") UUID id, @Valid @NotNull Client client) { logger.debug("PUT /clients/{}", id); Client updatedClient = clientService.update(id, client); return Response.ok(updatedClient).build(); } @DELETE @Path("/{id}") @RequirePermission(Permission.CLIENTS_DELETE) @Operation(summary = "Supprimer un client") @APIResponse(responseCode = "204", description = "Client supprimé avec succès") @APIResponse(responseCode = "404", description = "Client non trouvé") public Response deleteClient(@Parameter(description = "ID du client") @PathParam("id") UUID id) { logger.debug("DELETE /clients/{}", id); clientService.delete(id); return Response.noContent().build(); } // === ENDPOINTS STATISTIQUES - API CONTRACTS PRÉSERVÉS EXACTEMENT === @GET @Path("/count") @Operation(summary = "Compter le nombre de clients") @APIResponse(responseCode = "200", description = "Nombre de clients") public Response countClients() { logger.debug("GET /clients/count"); long count = clientService.count(); return Response.ok(count).build(); } }