package dev.lions.unionflow.server.payment;

import dev.lions.unionflow.server.api.payment.CheckoutRequest;
import dev.lions.unionflow.server.api.payment.PaymentException;
import dev.lions.unionflow.server.api.payment.PaymentStatus;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.util.Map;

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

class PaymentProviderTest {

    @Test
    @DisplayName("CheckoutRequest — montant nul lève IllegalArgumentException")
    void checkoutRequest_montantNull_throws() {
        assertThatIllegalArgumentException().isThrownBy(() ->
                new CheckoutRequest(null, "XOF", "+2250700000001",
                        "user@example.com", "REF-001", "https://ok", "https://cancel", Map.of())
        ).withMessageContaining("amount");
    }

    @Test
    @DisplayName("CheckoutRequest — montant négatif lève IllegalArgumentException")
    void checkoutRequest_montantNegatif_throws() {
        assertThatIllegalArgumentException().isThrownBy(() ->
                new CheckoutRequest(BigDecimal.valueOf(-100), "XOF", null,
                        null, "REF-002", "https://ok", "https://cancel", Map.of())
        ).withMessageContaining("amount");
    }

    @Test
    @DisplayName("CheckoutRequest — devise vide lève IllegalArgumentException")
    void checkoutRequest_deviseVide_throws() {
        assertThatIllegalArgumentException().isThrownBy(() ->
                new CheckoutRequest(BigDecimal.valueOf(5000), "", null,
                        null, "REF-003", "https://ok", "https://cancel", Map.of())
        ).withMessageContaining("currency");
    }

    @Test
    @DisplayName("CheckoutRequest — référence vide lève IllegalArgumentException")
    void checkoutRequest_referenceVide_throws() {
        assertThatIllegalArgumentException().isThrownBy(() ->
                new CheckoutRequest(BigDecimal.valueOf(5000), "XOF", null,
                        null, "", "https://ok", "https://cancel", Map.of())
        ).withMessageContaining("reference");
    }

    @Test
    @DisplayName("CheckoutRequest — valide sans erreur")
    void checkoutRequest_valide_ok() {
        assertThatNoException().isThrownBy(() ->
                new CheckoutRequest(BigDecimal.valueOf(10000), "XOF",
                        "+2250700000001", "user@test.ci",
                        "SOUSCRIPTION-UUID-123", "https://ok.ci", "https://cancel.ci",
                        Map.of("org", "mutuelle-1"))
        );
    }

    @Test
    @DisplayName("PaymentException — getHttpStatus et getProviderCode corrects")
    void paymentException_fields() {
        PaymentException ex = new PaymentException("WAVE", "Test error", 400);
        assertThat(ex.getHttpStatus()).isEqualTo(400);
        assertThat(ex.getProviderCode()).isEqualTo("WAVE");
        assertThat(ex.getMessage()).contains("WAVE").contains("Test error");
    }

    @Test
    @DisplayName("PaymentStatus — tous les statuts attendus présents")
    void paymentStatus_allValues() {
        var statuses = java.util.Arrays.stream(PaymentStatus.values())
                .map(Enum::name).toList();
        assertThat(statuses).contains("INITIATED", "PROCESSING", "SUCCESS", "FAILED", "CANCELLED", "EXPIRED");
    }
}
