package dev.lions.repositories; import dev.lions.models.Contact; import dev.lions.models.ContactStatus; import dev.lions.exceptions.RepositoryException; import jakarta.enterprise.context.ApplicationScoped; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.TypedQuery; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; /** * Repository gérant la persistance des contacts dans l'application. * Cette classe assure le stockage, la récupération et la gestion des contacts * en implémentant des fonctionnalités spécifiques au traitement des demandes * de contact. */ @Slf4j @ApplicationScoped public class ContactRepository extends BaseRepository { @PersistenceContext private EntityManager entityManager; /** * Recherche les contacts par statut avec tri par date de soumission. * Cette méthode permet de filtrer les contacts selon leur état de traitement. * * @param status Statut des contacts à rechercher * @return Liste des contacts correspondant au statut */ public List findByStatus(@NotNull ContactStatus status) { log.debug("Recherche des contacts avec le statut : {}", status); try { TypedQuery query = entityManager.createQuery( "SELECT c FROM Contact c " + "WHERE c.status = :status " + "ORDER BY c.submitDate DESC", Contact.class ); query.setParameter("status", status); return query.getResultList(); } catch (Exception e) { throw new RepositoryException( "Erreur lors de la recherche des contacts par statut", e); } } /** * Récupère les contacts non traités pour suivi. * Cette méthode retourne les contacts qui nécessitent une attention, * soit nouveaux soit en cours de traitement. * * @return Liste des contacts à traiter */ public List findUnprocessedContacts() { log.debug("Recherche des contacts non traités"); try { TypedQuery query = entityManager.createQuery( "SELECT c FROM Contact c " + "WHERE c.status IN (:statuses) " + "ORDER BY c.submitDate ASC", Contact.class ); query.setParameter("statuses", List.of(ContactStatus.NEW, ContactStatus.IN_PROGRESS)); return query.getResultList(); } catch (Exception e) { throw new RepositoryException( "Erreur lors de la recherche des contacts non traités", e); } } /** * Recherche les contacts soumis dans une période donnée. * * @param startDate Date de début de la période * @param endDate Date de fin de la période * @return Liste des contacts pour la période */ public List findBySubmitDateBetween( @NotNull LocalDateTime startDate, @NotNull LocalDateTime endDate) { log.debug("Recherche des contacts entre {} et {}", startDate, endDate); try { TypedQuery query = entityManager.createQuery( "SELECT c FROM Contact c " + "WHERE c.submitDate BETWEEN :startDate AND :endDate " + "ORDER BY c.submitDate DESC", Contact.class ); query.setParameter("startDate", startDate); query.setParameter("endDate", endDate); return query.getResultList(); } catch (Exception e) { throw new RepositoryException( "Erreur lors de la recherche des contacts par période", e); } } /** * Met à jour le statut d'un contact. * * @param contactId Identifiant du contact * @param newStatus Nouveau statut * @param processDate Date de traitement * @return Contact mis à jour */ public Optional updateStatus( @NotNull Long contactId, @NotNull ContactStatus newStatus, LocalDateTime processDate) { log.debug("Mise à jour du statut du contact {} vers {}", contactId, newStatus); try { Contact contact = entityManager.find(Contact.class, contactId); if (contact == null) { return Optional.empty(); } contact.setStatus(newStatus); if (processDate != null) { contact.setProcessDate(processDate); } Contact updatedContact = update(contact); log.info("Statut du contact {} mis à jour vers {}", contactId, newStatus); return Optional.of(updatedContact); } catch (Exception e) { throw new RepositoryException( "Erreur lors de la mise à jour du statut du contact", e); } } /** * Ajoute une note interne à un contact. * * @param contactId Identifiant du contact * @param note Note à ajouter * @return Contact mis à jour */ public Optional addInternalNote( @NotNull Long contactId, @NotNull String note) { log.debug("Ajout d'une note au contact {}", contactId); try { Contact contact = entityManager.find(Contact.class, contactId); if (contact == null) { return Optional.empty(); } String currentNotes = contact.getInternalNotes(); String updatedNotes = currentNotes == null ? note : currentNotes + "\n" + LocalDateTime.now() + ": " + note; contact.setInternalNotes(updatedNotes); Contact updatedContact = update(contact); log.info("Note ajoutée au contact {}", contactId); return Optional.of(updatedContact); } catch (Exception e) { throw new RepositoryException( "Erreur lors de l'ajout de la note au contact", e); } } }