package dev.lions.unionflow.server.entity;

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.*;

import java.time.LocalDateTime;

/**
 * Entité InscriptionEvenement représentant l'inscription d'un membre à un événement
 * 
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-15
 */
@Entity
@Table(name = "inscriptions_evenement", indexes = {
    @Index(name = "idx_inscription_membre", columnList = "membre_id"),
    @Index(name = "idx_inscription_evenement", columnList = "evenement_id"),
    @Index(name = "idx_inscription_date", columnList = "date_inscription")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
public class InscriptionEvenement extends PanacheEntity {

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "membre_id", nullable = false)
    private Membre membre;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "evenement_id", nullable = false)
    private Evenement evenement;

    @Builder.Default
    @Column(name = "date_inscription", nullable = false)
    private LocalDateTime dateInscription = LocalDateTime.now();

    @Enumerated(EnumType.STRING)
    @Column(name = "statut", length = 20)
    @Builder.Default
    private StatutInscription statut = StatutInscription.CONFIRMEE;

    @Column(name = "commentaire", length = 500)
    private String commentaire;

    @Builder.Default
    @Column(name = "date_creation", nullable = false)
    private LocalDateTime dateCreation = LocalDateTime.now();

    @Column(name = "date_modification")
    private LocalDateTime dateModification;

    /**
     * Énumération des statuts d'inscription
     */
    public enum StatutInscription {
        CONFIRMEE("Confirmée"),
        EN_ATTENTE("En attente"),
        ANNULEE("Annulée"),
        REFUSEE("Refusée");

        private final String libelle;

        StatutInscription(String libelle) {
            this.libelle = libelle;
        }

        public String getLibelle() {
            return libelle;
        }
    }

    // Méthodes utilitaires

    /**
     * Vérifie si l'inscription est confirmée
     * 
     * @return true si l'inscription est confirmée
     */
    public boolean isConfirmee() {
        return StatutInscription.CONFIRMEE.equals(this.statut);
    }

    /**
     * Vérifie si l'inscription est en attente
     * 
     * @return true si l'inscription est en attente
     */
    public boolean isEnAttente() {
        return StatutInscription.EN_ATTENTE.equals(this.statut);
    }

    /**
     * Vérifie si l'inscription est annulée
     * 
     * @return true si l'inscription est annulée
     */
    public boolean isAnnulee() {
        return StatutInscription.ANNULEE.equals(this.statut);
    }

    /**
     * Confirme l'inscription
     */
    public void confirmer() {
        this.statut = StatutInscription.CONFIRMEE;
        this.dateModification = LocalDateTime.now();
    }

    /**
     * Annule l'inscription
     * 
     * @param commentaire le commentaire d'annulation
     */
    public void annuler(String commentaire) {
        this.statut = StatutInscription.ANNULEE;
        this.commentaire = commentaire;
        this.dateModification = LocalDateTime.now();
    }

    /**
     * Met l'inscription en attente
     * 
     * @param commentaire le commentaire de mise en attente
     */
    public void mettreEnAttente(String commentaire) {
        this.statut = StatutInscription.EN_ATTENTE;
        this.commentaire = commentaire;
        this.dateModification = LocalDateTime.now();
    }

    /**
     * Refuse l'inscription
     * 
     * @param commentaire le commentaire de refus
     */
    public void refuser(String commentaire) {
        this.statut = StatutInscription.REFUSEE;
        this.commentaire = commentaire;
        this.dateModification = LocalDateTime.now();
    }

    // Callbacks JPA

    @PreUpdate
    public void preUpdate() {
        this.dateModification = LocalDateTime.now();
    }

    @Override
    public String toString() {
        return String.format("InscriptionEvenement{id=%d, membre=%s, evenement=%s, statut=%s, dateInscription=%s}",
            id,
            membre != null ? membre.getEmail() : "null",
            evenement != null ? evenement.getTitre() : "null",
            statut,
            dateInscription);
    }
}
