package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.wave.StatutWebhook;
import dev.lions.unionflow.server.api.enums.wave.TypeEvenementWebhook;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Entité WebhookWave pour le traitement des événements Wave
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(name = "webhooks_wave", indexes = {
    @Index(name = "idx_webhook_wave_event_id", columnList = "wave_event_id", unique = true),
    @Index(name = "idx_webhook_wave_statut", columnList = "statut_traitement"),
    @Index(name = "idx_webhook_wave_type", columnList = "type_evenement"),
    @Index(name = "idx_webhook_wave_transaction", columnList = "transaction_wave_id"),
    @Index(name = "idx_webhook_wave_paiement", columnList = "paiement_id")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class WebhookWave extends BaseEntity {

  /** Identifiant unique de l'événement Wave */
  @NotBlank
  @Column(name = "wave_event_id", unique = true, nullable = false, length = 100)
  private String waveEventId;

  /** Type d'événement */
  @Column(name = "type_evenement", length = 50)
  private String typeEvenement;

  /** Statut de traitement */
  @Builder.Default
  @Column(name = "statut_traitement", nullable = false, length = 30)
  private String statutTraitement = StatutWebhook.EN_ATTENTE.name();

  /** Payload JSON reçu */
  @Column(name = "payload", columnDefinition = "TEXT")
  private String payload;

  /** Signature de validation */
  @Column(name = "signature", length = 500)
  private String signature;

  /** Date de réception */
  @Column(name = "date_reception")
  private LocalDateTime dateReception;

  /** Date de traitement */
  @Column(name = "date_traitement")
  private LocalDateTime dateTraitement;

  /** Nombre de tentatives de traitement */
  @Builder.Default
  @Column(name = "nombre_tentatives", nullable = false)
  private Integer nombreTentatives = 0;

  /** Message d'erreur (si échec) */
  @Column(name = "message_erreur", length = 1000)
  private String messageErreur;

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

  // Relations
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "transaction_wave_id")
  private TransactionWave transactionWave;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "paiement_id")
  private Versement versement;

  /** Méthode métier pour vérifier si le webhook est traité */
  public boolean isTraite() {
    return StatutWebhook.TRAITE.name().equals(statutTraitement);
  }

  /** Méthode métier pour vérifier si le webhook peut être retenté */
  public boolean peutEtreRetente() {
    return (StatutWebhook.ECHOUE.name().equals(statutTraitement)
        || StatutWebhook.EN_ATTENTE.name().equals(statutTraitement))
        && (nombreTentatives == null || nombreTentatives < 5);
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (statutTraitement == null) {
      statutTraitement = StatutWebhook.EN_ATTENTE.name();
    }
    if (dateReception == null) {
      dateReception = LocalDateTime.now();
    }
    if (nombreTentatives == null) {
      nombreTentatives = 0;
    }
  }
}
