package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.Adhesion;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.TypedQuery;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Repository pour l'entité Adhesion
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-17
 */
@ApplicationScoped
public class AdhesionRepository extends BaseRepository<Adhesion> {

  public AdhesionRepository() {
    super(Adhesion.class);
  }

  /**
   * Trouve une adhésion par son numéro de référence
   *
   * @param numeroReference numéro de référence unique
   * @return Optional contenant l'adhésion si trouvée
   */
  public Optional<Adhesion> findByNumeroReference(String numeroReference) {
    TypedQuery<Adhesion> query =
        entityManager.createQuery(
            "SELECT a FROM Adhesion a WHERE a.numeroReference = :numeroReference", Adhesion.class);
    query.setParameter("numeroReference", numeroReference);
    return query.getResultStream().findFirst();
  }

  /**
   * Trouve toutes les adhésions d'un membre
   *
   * @param membreId identifiant du membre
   * @return liste des adhésions du membre
   */
  public List<Adhesion> findByMembreId(UUID membreId) {
    TypedQuery<Adhesion> query =
        entityManager.createQuery(
            "SELECT a FROM Adhesion a WHERE a.membre.id = :membreId", Adhesion.class);
    query.setParameter("membreId", membreId);
    return query.getResultList();
  }

  /**
   * Trouve toutes les adhésions d'une organisation
   *
   * @param organisationId identifiant de l'organisation
   * @return liste des adhésions de l'organisation
   */
  public List<Adhesion> findByOrganisationId(UUID organisationId) {
    TypedQuery<Adhesion> query =
        entityManager.createQuery(
            "SELECT a FROM Adhesion a WHERE a.organisation.id = :organisationId", Adhesion.class);
    query.setParameter("organisationId", organisationId);
    return query.getResultList();
  }

  /**
   * Trouve toutes les adhésions par statut
   *
   * @param statut statut de l'adhésion
   * @return liste des adhésions avec le statut spécifié
   */
  public List<Adhesion> findByStatut(String statut) {
    TypedQuery<Adhesion> query =
        entityManager.createQuery("SELECT a FROM Adhesion a WHERE a.statut = :statut", Adhesion.class);
    query.setParameter("statut", statut);
    return query.getResultList();
  }

  /**
   * Trouve toutes les adhésions en attente
   *
   * @return liste des adhésions en attente
   */
  public List<Adhesion> findEnAttente() {
    return findByStatut("EN_ATTENTE");
  }

  /**
   * Trouve toutes les adhésions approuvées en attente de paiement
   *
   * @return liste des adhésions approuvées non payées
   */
  public List<Adhesion> findApprouveesEnAttentePaiement() {
    TypedQuery<Adhesion> query =
        entityManager.createQuery(
            "SELECT a FROM Adhesion a WHERE a.statut = :statut AND (a.montantPaye IS NULL OR a.montantPaye < a.fraisAdhesion)",
            Adhesion.class);
    query.setParameter("statut", "APPROUVEE");
    return query.getResultList();
  }
}

