package dev.lions.unionflow.server.api.dto.paiement;

import com.fasterxml.jackson.annotation.JsonFormat;
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;

/**
 * DTO pour les sessions de paiement Wave Money (Checkout API) Représente une session de paiement
 * créée via l'API Wave Checkout
 *
 * <p>Basé sur l'API officielle Wave : https://docs.wave.com/business#checkout-api
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-10
 */
@Getter
@Setter
public class WaveCheckoutSessionDTO extends BaseDTO {

  private static final long serialVersionUID = 1L;

  /** ID de la session Wave (retourné par l'API) */
  @NotBlank(message = "L'ID de session Wave est obligatoire")
  private String waveSessionId;

  /** URL de la session de paiement Wave (générée par l'API Wave) */
  @Size(max = 500, message = "L'URL ne peut pas dépasser 500 caractères")
  private String waveUrl;

  /** Montant du paiement */
  @NotNull(message = "Le montant est obligatoire")
  @DecimalMin(value = "0.01", message = "Le montant doit être positif")
  @Digits(
      integer = 10,
      fraction = 2,
      message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales")
  private BigDecimal montant;

  /** Devise (XOF pour le Sénégal) */
  @NotBlank(message = "La devise est obligatoire")
  @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
  private String devise = "XOF";

  /** URL de succès (redirection après paiement réussi) */
  @NotBlank(message = "L'URL de succès est obligatoire")
  @Size(max = 500, message = "L'URL de succès ne peut pas dépasser 500 caractères")
  private String successUrl;

  /** URL d'erreur (redirection après échec) */
  @NotBlank(message = "L'URL d'erreur est obligatoire")
  @Size(max = 500, message = "L'URL d'erreur ne peut pas dépasser 500 caractères")
  private String errorUrl;

  /** Statut de la session */
  @NotNull(message = "Le statut est obligatoire")
  private StatutSession statut;

  /** ID de l'organisation qui effectue le paiement */
  private UUID organisationId;

  /** Nom de l'organisation */
  private String nomOrganisation;

  /** ID du membre qui effectue le paiement */
  private UUID membreId;

  /** Nom du membre */
  private String nomMembre;

  /** Type de paiement (COTISATION, ABONNEMENT, DON, AUTRE) */
  @Pattern(
      regexp = "^(COTISATION|ABONNEMENT|DON|EVENEMENT|FORMATION|AUTRE)$",
      message = "Type de paiement invalide")
  private String typePaiement;

  /** Référence du paiement dans UnionFlow */
  @Size(max = 100, message = "La référence ne peut pas dépasser 100 caractères")
  private String referenceUnionFlow;

  /** Description du paiement */
  @Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
  private String description;

  /** Nom du business affiché (override_business_name) */
  @Size(max = 100, message = "Le nom du business ne peut pas dépasser 100 caractères")
  private String nomBusinessAffiche;

  /** ID du marchand agrégé (si applicable) */
  private String aggregatedMerchantId;

  /** Date d'expiration de la session */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  private LocalDateTime dateExpiration;

  /** Date de completion du paiement */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  private LocalDateTime dateCompletion;

  /** Numéro de téléphone du payeur (si fourni) */
  @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide")
  private String telephonePayeur;

  /** Email du payeur (si fourni) */
  @Pattern(regexp = "^[A-Za-z0-9+_.-]+@(.+)$", message = "Format d'email invalide")
  private String emailPayeur;

  /** Adresse IP du client */
  private String adresseIpClient;

  /** User Agent du navigateur */
  @Size(max = 500, message = "Le User Agent ne peut pas dépasser 500 caractères")
  private String userAgent;

  /** Données de callback reçues de Wave */
  @Size(max = 2000, message = "Les données callback ne peuvent pas dépasser 2000 caractères")
  private String callbackData;

  /** Code d'erreur Wave (si échec) */
  private String codeErreurWave;

  /** Message d'erreur Wave (si échec) */
  @Size(max = 500, message = "Le message d'erreur ne peut pas dépasser 500 caractères")
  private String messageErreurWave;

  /** Nombre de tentatives de paiement */
  private Integer nombreTentatives;

  /** Session liée à un webhook */
  private Boolean webhookRecu;

  /** Date de réception du webhook */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  private LocalDateTime dateWebhook;

  /** Données du webhook reçu */
  @Size(max = 2000, message = "Les données webhook ne peuvent pas dépasser 2000 caractères")
  private String donneesWebhook;

  // Constructeurs
  public WaveCheckoutSessionDTO() {
    super();
    this.devise = "XOF";
    this.statut = StatutSession.PENDING;
    this.nombreTentatives = 0;
    this.webhookRecu = false;
  }

  public WaveCheckoutSessionDTO(BigDecimal montant, String successUrl, String errorUrl) {
    this();
    this.montant = montant;
    this.successUrl = successUrl;
    this.errorUrl = errorUrl;
  }

  // Getters et Setters générés automatiquement par Lombok @Getter/@Setter
}
