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

import static org.assertj.core.api.Assertions.assertThat;

import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
 * Tests unitaires pour WaveCheckoutSessionDTO
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-10
 */
@DisplayName("Tests WaveCheckoutSessionDTO")
class WaveCheckoutSessionDTOBasicTest {

  private WaveCheckoutSessionDTO session;

  @BeforeEach
  void setUp() {
    session = new WaveCheckoutSessionDTO();
  }

  @Test
  @DisplayName("Test constructeur par défaut")
  void testConstructeurParDefaut() {
    WaveCheckoutSessionDTO newSession = new WaveCheckoutSessionDTO();

    assertThat(newSession.getDevise()).isEqualTo("XOF");
    assertThat(newSession.getStatut()).isEqualTo(StatutSession.PENDING);
    assertThat(newSession.getNombreTentatives()).isEqualTo(0);
    assertThat(newSession.getWebhookRecu()).isFalse();
  }

  @Test
  @DisplayName("Test constructeur avec paramètres")
  void testConstructeurAvecParametres() {
    BigDecimal montant = new BigDecimal("50000.00");
    String successUrl = "https://example.com/success";
    String errorUrl = "https://example.com/error";

    WaveCheckoutSessionDTO newSession = new WaveCheckoutSessionDTO(montant, successUrl, errorUrl);

    assertThat(newSession.getMontant()).isEqualByComparingTo(montant);
    assertThat(newSession.getSuccessUrl()).isEqualTo(successUrl);
    assertThat(newSession.getErrorUrl()).isEqualTo(errorUrl);
    // Vérifier les valeurs par défaut
    assertThat(newSession.getDevise()).isEqualTo("XOF");
    assertThat(newSession.getStatut()).isEqualTo(StatutSession.PENDING);
    assertThat(newSession.getNombreTentatives()).isEqualTo(0);
    assertThat(newSession.getWebhookRecu()).isFalse();
  }

  @Test
  @DisplayName("Test tous les getters/setters")
  void testTousLesGettersSetters() {
    // Données de test
    String waveSessionId = "wave_session_123";
    String waveUrl = "https://checkout.wave.com/session/123";
    BigDecimal montant = new BigDecimal("75000.50");
    String devise = "XOF";
    String successUrl = "https://example.com/success";
    String errorUrl = "https://example.com/error";
    StatutSession statut = StatutSession.COMPLETED;
    UUID organisationId = UUID.randomUUID();
    String nomOrganisation = "Lions Club Dakar";
    UUID membreId = UUID.randomUUID();
    String nomMembre = "Jean Dupont";
    String typePaiement = "COTISATION";
    String referenceUnionFlow = "UF-2025-001";
    String description = "Paiement cotisation mensuelle";
    String nomBusinessAffiche = "UnionFlow";
    String aggregatedMerchantId = "merchant_123";
    LocalDateTime dateExpiration = LocalDateTime.now().plusHours(1);
    LocalDateTime dateCompletion = LocalDateTime.now();
    String telephonePayeur = "+221771234567";
    String emailPayeur = "jean.dupont@example.com";
    String adresseIpClient = "192.168.1.1";
    String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)";
    String callbackData = "{\"status\":\"success\"}";
    String codeErreurWave = "E001";
    String messageErreurWave = "Erreur de paiement";
    Integer nombreTentatives = 3;
    Boolean webhookRecu = true;
    LocalDateTime dateWebhook = LocalDateTime.now();
    String donneesWebhook = "{\"event\":\"payment.completed\"}";

    // Test des setters
    session.setWaveSessionId(waveSessionId);
    session.setWaveUrl(waveUrl);
    session.setMontant(montant);
    session.setDevise(devise);
    session.setSuccessUrl(successUrl);
    session.setErrorUrl(errorUrl);
    session.setStatut(statut);
    session.setOrganisationId(organisationId);
    session.setNomOrganisation(nomOrganisation);
    session.setMembreId(membreId);
    session.setNomMembre(nomMembre);
    session.setTypePaiement(typePaiement);
    session.setReferenceUnionFlow(referenceUnionFlow);
    session.setDescription(description);
    session.setNomBusinessAffiche(nomBusinessAffiche);
    session.setAggregatedMerchantId(aggregatedMerchantId);
    session.setDateExpiration(dateExpiration);
    session.setDateCompletion(dateCompletion);
    session.setTelephonePayeur(telephonePayeur);
    session.setEmailPayeur(emailPayeur);
    session.setAdresseIpClient(adresseIpClient);
    session.setUserAgent(userAgent);
    session.setCallbackData(callbackData);
    session.setCodeErreurWave(codeErreurWave);
    session.setMessageErreurWave(messageErreurWave);
    session.setNombreTentatives(nombreTentatives);
    session.setWebhookRecu(webhookRecu);
    session.setDateWebhook(dateWebhook);
    session.setDonneesWebhook(donneesWebhook);

    // Test des getters
    assertThat(session.getWaveSessionId()).isEqualTo(waveSessionId);
    assertThat(session.getWaveUrl()).isEqualTo(waveUrl);
    assertThat(session.getMontant()).isEqualByComparingTo(montant);
    assertThat(session.getDevise()).isEqualTo(devise);
    assertThat(session.getSuccessUrl()).isEqualTo(successUrl);
    assertThat(session.getErrorUrl()).isEqualTo(errorUrl);
    assertThat(session.getStatut()).isEqualTo(statut);
    assertThat(session.getOrganisationId()).isEqualTo(organisationId);
    assertThat(session.getNomOrganisation()).isEqualTo(nomOrganisation);
    assertThat(session.getMembreId()).isEqualTo(membreId);
    assertThat(session.getNomMembre()).isEqualTo(nomMembre);
    assertThat(session.getTypePaiement()).isEqualTo(typePaiement);
    assertThat(session.getReferenceUnionFlow()).isEqualTo(referenceUnionFlow);
    assertThat(session.getDescription()).isEqualTo(description);
    assertThat(session.getNomBusinessAffiche()).isEqualTo(nomBusinessAffiche);
    assertThat(session.getAggregatedMerchantId()).isEqualTo(aggregatedMerchantId);
    assertThat(session.getDateExpiration()).isEqualTo(dateExpiration);
    assertThat(session.getDateCompletion()).isEqualTo(dateCompletion);
    assertThat(session.getTelephonePayeur()).isEqualTo(telephonePayeur);
    assertThat(session.getEmailPayeur()).isEqualTo(emailPayeur);
    assertThat(session.getAdresseIpClient()).isEqualTo(adresseIpClient);
    assertThat(session.getUserAgent()).isEqualTo(userAgent);
    assertThat(session.getCallbackData()).isEqualTo(callbackData);
    assertThat(session.getCodeErreurWave()).isEqualTo(codeErreurWave);
    assertThat(session.getMessageErreurWave()).isEqualTo(messageErreurWave);
    assertThat(session.getNombreTentatives()).isEqualTo(nombreTentatives);
    assertThat(session.getWebhookRecu()).isEqualTo(webhookRecu);
    assertThat(session.getDateWebhook()).isEqualTo(dateWebhook);
    assertThat(session.getDonneesWebhook()).isEqualTo(donneesWebhook);
  }

  @Test
  @DisplayName("Test toString")
  void testToString() {
    session.setWaveSessionId("wave_123");
    session.setMontant(new BigDecimal("50000.00"));
    session.setStatut(StatutSession.PENDING);

    String result = session.toString();
    assertThat(result).isNotNull();
    assertThat(result).contains("WaveCheckoutSessionDTO");
  }

  @Test
  @DisplayName("Test types de paiement valides")
  void testTypesPaiementValides() {
    String[] typesValides = {"COTISATION", "ABONNEMENT", "DON", "EVENEMENT", "FORMATION", "AUTRE"};
    
    for (String type : typesValides) {
      session.setTypePaiement(type);
      assertThat(session.getTypePaiement()).isEqualTo(type);
    }
  }

  @Test
  @DisplayName("Test statuts de session")
  void testStatutsSession() {
    StatutSession[] statuts = StatutSession.values();
    
    for (StatutSession statut : statuts) {
      session.setStatut(statut);
      assertThat(session.getStatut()).isEqualTo(statut);
    }
  }

  @Test
  @DisplayName("Test valeurs par défaut")
  void testValeursParDefaut() {
    WaveCheckoutSessionDTO newSession = new WaveCheckoutSessionDTO();
    
    assertThat(newSession.getDevise()).isEqualTo("XOF");
    assertThat(newSession.getStatut()).isEqualTo(StatutSession.PENDING);
    assertThat(newSession.getNombreTentatives()).isEqualTo(0);
    assertThat(newSession.getWebhookRecu()).isFalse();
  }

  @Test
  @DisplayName("Test gestion des erreurs")
  void testGestionErreurs() {
    session.setCodeErreurWave("E001");
    session.setMessageErreurWave("Paiement échoué");
    session.setStatut(StatutSession.FAILED);
    
    assertThat(session.getCodeErreurWave()).isEqualTo("E001");
    assertThat(session.getMessageErreurWave()).isEqualTo("Paiement échoué");
    assertThat(session.getStatut()).isEqualTo(StatutSession.FAILED);
  }

  @Test
  @DisplayName("Test gestion webhook")
  void testGestionWebhook() {
    LocalDateTime dateWebhook = LocalDateTime.now();
    String donneesWebhook = "{\"event\":\"payment.completed\"}";
    
    session.setWebhookRecu(true);
    session.setDateWebhook(dateWebhook);
    session.setDonneesWebhook(donneesWebhook);
    
    assertThat(session.getWebhookRecu()).isTrue();
    assertThat(session.getDateWebhook()).isEqualTo(dateWebhook);
    assertThat(session.getDonneesWebhook()).isEqualTo(donneesWebhook);
  }
}
