package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.wave.StatutWebhook;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.UUID;

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

@DisplayName("WebhookWave")
class WebhookWaveTest {

    @Test
    @DisplayName("getters/setters")
    void gettersSetters() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("evt-123");
        w.setTypeEvenement("PAYMENT_SUCCESS");
        w.setStatutTraitement(StatutWebhook.TRAITE.name());
        w.setPayload("{}");
        w.setDateReception(LocalDateTime.now());
        w.setNombreTentatives(1);

        assertThat(w.getWaveEventId()).isEqualTo("evt-123");
        assertThat(w.getTypeEvenement()).isEqualTo("PAYMENT_SUCCESS");
        assertThat(w.getStatutTraitement()).isEqualTo("TRAITE");
    }

    @Test
    @DisplayName("isTraite")
    void isTraite() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("x");
        w.setStatutTraitement(StatutWebhook.TRAITE.name());
        assertThat(w.isTraite()).isTrue();
        w.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
        assertThat(w.isTraite()).isFalse();
    }

    @Test
    @DisplayName("peutEtreRetente")
    void peutEtreRetente() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("x");
        w.setStatutTraitement(StatutWebhook.ECHOUE.name());
        w.setNombreTentatives(2);
        assertThat(w.peutEtreRetente()).isTrue();
        w.setNombreTentatives(5);
        assertThat(w.peutEtreRetente()).isFalse();
    }

    @Test
    @DisplayName("peutEtreRetente: false si statut TRAITE (ni ECHOUE ni EN_ATTENTE)")
    void peutEtreRetente_false_whenTraite() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("x");
        w.setStatutTraitement(StatutWebhook.TRAITE.name());
        w.setNombreTentatives(1);
        assertThat(w.peutEtreRetente()).isFalse();
    }

    @Test
    @DisplayName("equals et hashCode")
    void equalsHashCode() {
        UUID id = UUID.randomUUID();
        WebhookWave a = new WebhookWave();
        a.setId(id);
        a.setWaveEventId("evt-1");
        a.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
        WebhookWave b = new WebhookWave();
        b.setId(id);
        b.setWaveEventId("evt-1");
        b.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("toString non null")
    void toString_nonNull() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("x");
        w.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
        assertThat(w.toString()).isNotNull().isNotEmpty();
    }

    @Test
    @DisplayName("peutEtreRetente: true si nombreTentatives null et EN_ATTENTE")
    void peutEtreRetente_nombreTentativesNull_returnsTrue() {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("x");
        w.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
        w.setNombreTentatives(null);
        assertThat(w.peutEtreRetente()).isTrue();
    }

    @Test
    @DisplayName("onCreate: initialise les défauts si null")
    void onCreate_setsDefaults() throws Exception {
        WebhookWave w = new WebhookWave();
        w.setWaveEventId("evt-onc");
        w.setStatutTraitement(null);
        w.setDateReception(null);
        w.setNombreTentatives(null);

        Method onCreate = WebhookWave.class.getDeclaredMethod("onCreate");
        onCreate.setAccessible(true);
        onCreate.invoke(w);

        assertThat(w.getStatutTraitement()).isEqualTo(StatutWebhook.EN_ATTENTE.name());
        assertThat(w.getDateReception()).isNotNull();
        assertThat(w.getNombreTentatives()).isEqualTo(0);
    }
}
