package dev.lions.unionflow.server.repository;

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

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

  /** Trouve un paiement actif par son UUID. */
  public Optional<Paiement> findPaiementById(UUID id) {
    return find("id = ?1 AND actif = true", id).firstResultOptional();
  }

  /** Trouve un paiement par son numéro de référence. */
  public Optional<Paiement> findByNumeroReference(String numeroReference) {
    return find("numeroReference", numeroReference).firstResultOptional();
  }

  /** Tous les paiements actifs d'un membre, triés par date décroissante. */
  public List<Paiement> findByMembreId(UUID membreId) {
    return find(
            "membre.id = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            membreId)
        .list();
  }

  /** Paiements actifs par statut (valeur String), triés par date décroissante. */
  public List<Paiement> findByStatut(String statut) {
    return find(
            "statutPaiement = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            statut)
        .list();
  }

  /** Paiements actifs par méthode (valeur String), triés par date décroissante. */
  public List<Paiement> findByMethode(String methode) {
    return find(
            "methodePaiement = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            methode)
        .list();
  }

  /** Paiements validés dans une période, triés par date de validation décroissante. */
  public List<Paiement> findValidesParPeriode(LocalDateTime dateDebut, LocalDateTime dateFin) {
    return find(
            "statutPaiement = 'VALIDE' AND dateValidation >= ?1 AND dateValidation <= ?2 AND actif = true",
            Sort.by("dateValidation", Sort.Direction.Descending),
            dateDebut,
            dateFin)
        .list();
  }

  /** Somme des montants validés sur une période. */
  public BigDecimal calculerMontantTotalValides(LocalDateTime dateDebut, LocalDateTime dateFin) {
    return findValidesParPeriode(dateDebut, dateFin).stream()
        .map(Paiement::getMontant)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  }
}
