package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.api.enums.membre.StatutMembre;
import dev.lions.unionflow.server.entity.MembreOrganisation;
import jakarta.enterprise.context.ApplicationScoped;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Repository pour le lien Membre–Organisation (adhésion).
 */
@ApplicationScoped
public class MembreOrganisationRepository extends BaseRepository<MembreOrganisation> {

    public MembreOrganisationRepository() {
        super(MembreOrganisation.class);
    }

    /**
     * Trouve le lien membre-organisation s'il existe.
     */
    public Optional<MembreOrganisation> findByMembreIdAndOrganisationId(UUID membreId, UUID organisationId) {
        return find("membre.id = ?1 and organisation.id = ?2", membreId, organisationId).firstResultOptional();
    }

    /**
     * Trouve la première organisation d'un membre (utile pour l'OrgAdmin).
     */
    public Optional<MembreOrganisation> findFirstByMembreId(UUID membreId) {
        return find("membre.id = ?1", membreId).firstResultOptional();
    }

    /**
     * Trouve tous les liens actifs pour une organisation (pour l'activation du compte admin).
     */
    public List<MembreOrganisation> findAllByOrganisationId(UUID organisationId) {
        return find("organisation.id = ?1 and membre.actif = true", organisationId).list();
    }

    /**
     * Trouve toutes les organisations auxquelles un membre est rattaché (multi-org).
     */
    public List<MembreOrganisation> findAllByMembreId(UUID membreId) {
        return find("membre.id = ?1", membreId).list();
    }

    /**
     * Trouve toutes les organisations actives d'un membre (statut ACTIF).
     */
    public List<MembreOrganisation> findOrganisationsActivesParMembre(UUID membreId) {
        return find("membre.id = ?1 and statutMembre = 'ACTIF'", membreId).list();
    }

    /**
     * Trouve toutes les invitations en attente dont la date d'expiration est dépassée.
     */
    public List<MembreOrganisation> findInvitationsExpirees(LocalDateTime now) {
        return find("statutMembre = ?1 and dateExpirationInvitation is not null and dateExpirationInvitation < ?2",
                StatutMembre.INVITE, now).list();
    }

    /**
     * Trouve les invitations dont la date d'expiration arrive dans les prochaines 24h.
     * Utile pour envoyer un rappel avant expiration.
     */
    public List<MembreOrganisation> findInvitationsExpirantBientot(LocalDateTime from, LocalDateTime to) {
        return find("statutMembre = ?1 and dateExpirationInvitation >= ?2 and dateExpirationInvitation < ?3",
                StatutMembre.INVITE, from, to).list();
    }

    /**
     * Trouve tous les membres actifs d'une organisation (pour les rappels de cotisation).
     */
    public List<MembreOrganisation> findMembresActifsParOrganisation(UUID organisationId) {
        return find("organisation.id = ?1 and statutMembre = ?2",
                organisationId, StatutMembre.ACTIF).list();
    }

    /**
     * Trouve le lien membre-organisation par email du membre et ID de l'organisation.
     */
    public Optional<MembreOrganisation> findByMembreEmailAndOrganisationId(String email, UUID organisationId) {
        return find("membre.email = ?1 and organisation.id = ?2", email, organisationId).firstResultOptional();
    }

    /**
     * Trouve les membres ayant un rôle donné dans une organisation.
     */
    public List<MembreOrganisation> findByRoleOrgAndOrganisationId(String roleOrg, UUID organisationId) {
        return find("roleOrg = ?1 and organisation.id = ?2 and membre.actif = true", roleOrg, organisationId).list();
    }

    /**
     * Trouve les membres en attente de validation depuis plus de N jours.
     */
    public List<MembreOrganisation> findMembresEnAttenteDepuis(LocalDateTime avant) {
        return find("statutMembre = ?1 and dateInvitation is not null and dateInvitation < ?2",
                StatutMembre.EN_ATTENTE_VALIDATION, avant).list();
    }
}
