package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.Notification;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Repository pour l'entité Notification
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@ApplicationScoped
public class NotificationRepository implements PanacheRepositoryBase<Notification, UUID> {

  /**
   * Trouve une notification par son UUID
   *
   * @param id UUID de la notification
   * @return Notification ou Optional.empty()
   */
  public Optional<Notification> findNotificationById(UUID id) {
    return find("id = ?1", id).firstResultOptional();
  }

  /**
   * Trouve toutes les notifications d'un membre
   *
   * @param membreId ID du membre
   * @return Liste des notifications
   */
  public List<Notification> findByMembreId(UUID membreId) {
    return find("membre.id = ?1 ORDER BY dateEnvoiPrevue DESC, dateCreation DESC", membreId).list();
  }

  /**
   * Trouve toutes les notifications non lues d'un membre
   *
   * @param membreId ID du membre
   * @return Liste des notifications non lues
   */
  public List<Notification> findNonLuesByMembreId(UUID membreId) {
    return find(
        "membre.id = ?1 AND statut = ?2 ORDER BY priorite ASC, dateEnvoiPrevue DESC",
        membreId,
        "NON_LUE")
        .list();
  }

  /**
   * Trouve toutes les notifications d'une organisation
   *
   * @param organisationId ID de l'organisation
   * @return Liste des notifications
   */
  public List<Notification> findByOrganisationId(UUID organisationId) {
    return find("organisation.id = ?1 ORDER BY dateEnvoiPrevue DESC, dateCreation DESC", organisationId)
        .list();
  }

  /**
   * Trouve les notifications par type
   *
   * @param type Type de notification
   * @return Liste des notifications
   */
  public List<Notification> findByType(String type) {
    return find("typeNotification = ?1 ORDER BY dateEnvoiPrevue DESC", type).list();
  }

  /**
   * Trouve les notifications par statut
   *
   * @param statut Statut de la notification
   * @return Liste des notifications
   */
  public List<Notification> findByStatut(String statut) {
    return find("statut = ?1 ORDER BY dateEnvoiPrevue DESC", statut).list();
  }

  /**
   * Trouve les notifications par priorité
   *
   * @param priorite Priorité de la notification
   * @return Liste des notifications
   */
  public List<Notification> findByPriorite(String priorite) {
    return find("priorite = ?1 ORDER BY dateEnvoiPrevue DESC", priorite).list();
  }

  /**
   * Trouve les notifications en attente d'envoi
   *
   * @return Liste des notifications en attente
   */
  public List<Notification> findEnAttenteEnvoi() {
    LocalDateTime maintenant = LocalDateTime.now();
    return find(
        "statut IN (?1, ?2) AND dateEnvoiPrevue <= ?3 ORDER BY priorite DESC, dateEnvoiPrevue ASC",
        "EN_ATTENTE",
        "PROGRAMMEE",
        maintenant)
        .list();
  }

  /**
   * Trouve les notifications échouées pouvant être retentées
   *
   * @return Liste des notifications échouées
   */
  public List<Notification> findEchoueesRetentables() {
    return find(
        "statut IN (?1, ?2) AND (nombreTentatives IS NULL OR nombreTentatives < 5) ORDER BY dateEnvoiPrevue ASC",
        "ECHEC_ENVOI",
        "ERREUR_TECHNIQUE")
        .list();
  }
}
