package com.lions.dev.service; import com.lions.dev.dto.request.establishment.EstablishmentRatingRequestDTO; import com.lions.dev.entity.establishment.Establishment; import com.lions.dev.entity.establishment.EstablishmentRating; import com.lions.dev.entity.users.Users; import com.lions.dev.repository.EstablishmentRatingRepository; import com.lions.dev.repository.EstablishmentRepository; import com.lions.dev.repository.UsersRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import org.jboss.logging.Logger; import java.util.Map; import java.util.UUID; /** * Service de gestion des notations d'établissements. * Ce service contient la logique métier pour soumettre, modifier et récupérer les notes. */ @ApplicationScoped public class EstablishmentRatingService { @Inject EstablishmentRatingRepository ratingRepository; @Inject EstablishmentRepository establishmentRepository; @Inject UsersRepository usersRepository; private static final Logger LOG = Logger.getLogger(EstablishmentRatingService.class); /** * Soumet une nouvelle note pour un établissement. * * @param establishmentId L'ID de l'établissement * @param userId L'ID de l'utilisateur * @param requestDTO Le DTO contenant la note et le commentaire * @return La note créée */ @Transactional public EstablishmentRating submitRating(UUID establishmentId, UUID userId, EstablishmentRatingRequestDTO requestDTO) { LOG.info("Soumission d'une note pour l'établissement " + establishmentId + " par l'utilisateur " + userId); // Vérifier que l'établissement existe Establishment establishment = establishmentRepository.findById(establishmentId); if (establishment == null) { LOG.error("Établissement non trouvé avec l'ID : " + establishmentId); throw new RuntimeException("Établissement non trouvé"); } // Vérifier que l'utilisateur existe Users user = usersRepository.findById(userId); if (user == null) { LOG.error("Utilisateur non trouvé avec l'ID : " + userId); throw new RuntimeException("Utilisateur non trouvé"); } // Vérifier qu'il n'y a pas déjà une note de cet utilisateur EstablishmentRating existingRating = ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId); if (existingRating != null) { LOG.error("L'utilisateur " + userId + " a déjà noté l'établissement " + establishmentId); throw new RuntimeException("Vous avez déjà noté cet établissement. Utilisez la mise à jour pour modifier votre note."); } // Créer la note EstablishmentRating rating = new EstablishmentRating(establishment, user, requestDTO.getRating()); rating.setComment(requestDTO.getComment()); ratingRepository.persist(rating); // Mettre à jour les statistiques de l'établissement updateEstablishmentRatingStats(establishmentId); LOG.info("Note soumise avec succès : " + rating.getId()); return rating; } /** * Met à jour une note existante. * * @param establishmentId L'ID de l'établissement * @param userId L'ID de l'utilisateur * @param requestDTO Le DTO contenant la nouvelle note et le commentaire * @return La note mise à jour */ @Transactional public EstablishmentRating updateRating(UUID establishmentId, UUID userId, EstablishmentRatingRequestDTO requestDTO) { LOG.info("Mise à jour de la note pour l'établissement " + establishmentId + " par l'utilisateur " + userId); // Récupérer la note existante EstablishmentRating rating = ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId); if (rating == null) { LOG.error("Note non trouvée pour l'établissement " + establishmentId + " et l'utilisateur " + userId); throw new RuntimeException("Note non trouvée. Utilisez la soumission pour créer une nouvelle note."); } // Mettre à jour la note rating.updateRating(requestDTO.getRating(), requestDTO.getComment()); ratingRepository.persist(rating); // Mettre à jour les statistiques de l'établissement updateEstablishmentRatingStats(establishmentId); LOG.info("Note mise à jour avec succès : " + rating.getId()); return rating; } /** * Récupère la note d'un utilisateur pour un établissement. * * @param establishmentId L'ID de l'établissement * @param userId L'ID de l'utilisateur * @return La note de l'utilisateur ou null si pas encore noté */ public EstablishmentRating getUserRating(UUID establishmentId, UUID userId) { LOG.info("Récupération de la note de l'utilisateur " + userId + " pour l'établissement " + establishmentId); return ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId); } /** * Récupère les statistiques de notation d'un établissement. * * @param establishmentId L'ID de l'établissement * @return Map contenant averageRating, totalRatings et distribution */ public Map getRatingStats(UUID establishmentId) { LOG.info("Récupération des statistiques de notation pour l'établissement " + establishmentId); Double averageRating = ratingRepository.calculateAverageRating(establishmentId); Long totalRatings = ratingRepository.countByEstablishmentId(establishmentId); Map distribution = ratingRepository.calculateRatingDistribution(establishmentId); return Map.of( "averageRating", averageRating, "totalRatingsCount", totalRatings.intValue(), "ratingDistribution", distribution ); } /** * Met à jour les statistiques de notation d'un établissement. * Cette méthode est appelée après chaque création/modification de note. * Note: Cette méthode est appelée depuis des méthodes déjà transactionnelles, * donc pas besoin de l'annotation @Transactional ici. * * @param establishmentId L'ID de l'établissement */ private void updateEstablishmentRatingStats(UUID establishmentId) { Establishment establishment = establishmentRepository.findById(establishmentId); if (establishment == null) { return; } Double averageRating = ratingRepository.calculateAverageRating(establishmentId); Long totalRatings = ratingRepository.countByEstablishmentId(establishmentId); establishment.setAverageRating(averageRating); establishment.setTotalRatingsCount(totalRatings.intValue()); establishmentRepository.persist(establishment); LOG.info("Statistiques mises à jour pour l'établissement " + establishmentId + " : moyenne = " + averageRating + ", total = " + totalRatings); } }