package dev.lions.unionflow.server.payment.pispi;

import dev.lions.unionflow.server.api.payment.PaymentException;
import dev.lions.unionflow.server.payment.pispi.dto.Pacs008Request;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.math.BigDecimal;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class PispiClientTest {

    @Mock
    PispiAuth pispiAuth;

    private PispiClient client;

    @BeforeEach
    void setUp() throws Exception {
        client = new PispiClient();

        Field authField = PispiClient.class.getDeclaredField("pispiAuth");
        authField.setAccessible(true);
        authField.set(client, pispiAuth);

        Field baseUrlField = PispiClient.class.getDeclaredField("baseUrl");
        baseUrlField.setAccessible(true);
        baseUrlField.set(client, "http://localhost:1"); // unreachable endpoint

        Field institutionField = PispiClient.class.getDeclaredField("institutionCode");
        institutionField.setAccessible(true);
        institutionField.set(client, "TEST-BIC");
    }

    @Test
    void initiatePayment_whenAuthFails_throwsPaymentException() throws Exception {
        when(pispiAuth.getAccessToken()).thenThrow(
                new PaymentException("PISPI", "OAuth2 failed", 503));

        Pacs008Request request = new Pacs008Request();
        request.setEndToEndId("E2E-001");
        request.setAmount(BigDecimal.valueOf(5000));
        request.setCurrency("XOF");

        assertThatThrownBy(() -> client.initiatePayment(request))
                .isInstanceOf(PaymentException.class);
    }

    @Test
    void initiatePayment_whenHttpCallFails_throwsPaymentException() throws Exception {
        when(pispiAuth.getAccessToken()).thenReturn("mock-token");

        Pacs008Request request = new Pacs008Request();
        request.setEndToEndId("E2E-002");
        request.setAmount(BigDecimal.valueOf(1000));
        request.setCurrency("XOF");

        // http://localhost:1 will refuse connection → wrapped as PaymentException
        assertThatThrownBy(() -> client.initiatePayment(request))
                .isInstanceOf(PaymentException.class)
                .hasMessageContaining("PI-SPI");
    }

    @Test
    void getStatus_whenAuthFails_throwsPaymentException() throws Exception {
        when(pispiAuth.getAccessToken()).thenThrow(
                new PaymentException("PISPI", "OAuth2 failed", 503));

        assertThatThrownBy(() -> client.getStatus("TXN-001"))
                .isInstanceOf(PaymentException.class);
    }

    @Test
    void getStatus_whenHttpCallFails_throwsPaymentException() throws Exception {
        when(pispiAuth.getAccessToken()).thenReturn("mock-token");

        // http://localhost:1 will refuse connection → wrapped as PaymentException
        assertThatThrownBy(() -> client.getStatus("TXN-002"))
                .isInstanceOf(PaymentException.class)
                .hasMessageContaining("PI-SPI");
    }
}
