package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.api.enums.paiement.MethodePaiement;
import dev.lions.unionflow.server.api.enums.paiement.StatutPaiement;
import dev.lions.unionflow.server.entity.Paiement;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Page;
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 par son UUID
   *
   * @param id UUID du paiement
   * @return Paiement ou Optional.empty()
   */
  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
   *
   * @param numeroReference Numéro de référence
   * @return Paiement ou Optional.empty()
   */
  public Optional<Paiement> findByNumeroReference(String numeroReference) {
    return find("numeroReference", numeroReference).firstResultOptional();
  }

  /**
   * Trouve tous les paiements d'un membre
   *
   * @param membreId ID du membre
   * @return Liste des paiements
   */
  public List<Paiement> findByMembreId(UUID membreId) {
    return find("membre.id = ?1 AND actif = true", Sort.by("datePaiement", Sort.Direction.Descending), membreId)
        .list();
  }

  /**
   * Trouve les paiements par statut
   *
   * @param statut Statut du paiement
   * @return Liste des paiements
   */
  public List<Paiement> findByStatut(StatutPaiement statut) {
    return find("statutPaiement = ?1 AND actif = true", Sort.by("datePaiement", Sort.Direction.Descending), statut.name())
        .list();
  }

  /**
   * Trouve les paiements par méthode
   *
   * @param methode Méthode de paiement
   * @return Liste des paiements
   */
  public List<Paiement> findByMethode(MethodePaiement methode) {
    return find("methodePaiement = ?1 AND actif = true", Sort.by("datePaiement", Sort.Direction.Descending), methode.name())
        .list();
  }

  /**
   * Trouve les paiements validés dans une période
   *
   * @param dateDebut Date de début
   * @param dateFin Date de fin
   * @return Liste des paiements
   */
  public List<Paiement> findValidesParPeriode(LocalDateTime dateDebut, LocalDateTime dateFin) {
    return find(
            "statutPaiement = ?1 AND dateValidation >= ?2 AND dateValidation <= ?3 AND actif = true",
            Sort.by("dateValidation", Sort.Direction.Descending),
            StatutPaiement.VALIDE.name(),
            dateDebut,
            dateFin)
        .list();
  }

  /**
   * Calcule le montant total des paiements validés dans une période
   *
   * @param dateDebut Date de début
   * @param dateFin Date de fin
   * @return Montant total
   */
  public BigDecimal calculerMontantTotalValides(LocalDateTime dateDebut, LocalDateTime dateFin) {
    List<Paiement> paiements = findValidesParPeriode(dateDebut, dateFin);
    return paiements.stream()
        .map(Paiement::getMontant)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  }
}



