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.Versement;
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é {@link Versement}.
 *
 * @author UnionFlow Team
 * @version 4.0
 * @since 2026-04-13
 */
@ApplicationScoped
public class VersementRepository implements PanacheRepositoryBase<Versement, UUID> {

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

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

    /** Liste tous les versements actifs d'un membre, les plus récents d'abord. */
    public List<Versement> findByMembreId(UUID membreId) {
        return find(
            "membre.id = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            membreId
        ).list();
    }

    /** Liste les versements par statut. */
    public List<Versement> findByStatut(StatutPaiement statut) {
        return find(
            "statutPaiement = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            statut.name()
        ).list();
    }

    /** Liste les versements par méthode. */
    public List<Versement> findByMethode(MethodePaiement methode) {
        return find(
            "methodePaiement = ?1 AND actif = true",
            Sort.by("datePaiement", Sort.Direction.Descending),
            methode.name()
        ).list();
    }

    /** Liste les versements confirmés dans une période donnée. */
    public List<Versement> findConfirmesParPeriode(LocalDateTime dateDebut, LocalDateTime dateFin) {
        return find(
            "statutPaiement IN ('CONFIRME', 'VALIDE') "
                + "AND dateValidation >= ?1 AND dateValidation <= ?2 AND actif = true",
            Sort.by("dateValidation", Sort.Direction.Descending),
            dateDebut,
            dateFin
        ).list();
    }

    /** Calcule le montant total des versements confirmés dans une période. */
    public BigDecimal calculerMontantTotalConfirmes(LocalDateTime dateDebut, LocalDateTime dateFin) {
        return findConfirmesParPeriode(dateDebut, dateFin).stream()
            .map(Versement::getMontant)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}
