package dev.lions.unionflow.server.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import lombok.*;

/**
 * Entité InscriptionEvenement représentant l'inscription d'un membre à un
 * événement
 *
 * @author UnionFlow Team
 * @version 2.0
 * @since 2025-01-16
 */
@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 = true)
public class InscriptionEvenement extends BaseEntity {

  @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();

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

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

  /** Énumération des statuts d'inscription (pour constantes) */
  public enum StatutInscription {
    CONFIRMEE,
    EN_ATTENTE,
    ANNULEE,
    REFUSEE;
  }

  // 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.name().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.name().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.name().equals(this.statut);
  }

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

  /**
   * Annule l'inscription
   *
   * @param commentaire le commentaire d'annulation
   */
  public void annuler(String commentaire) {
    this.statut = StatutInscription.ANNULEE.name();
    this.commentaire = commentaire;
    setDateModification(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.name();
    this.commentaire = commentaire;
    setDateModification(LocalDateTime.now());
  }

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

  // Callbacks JPA

  @PreUpdate
  public void preUpdate() {
    super.onUpdate();
  }

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