package dev.lions.unionflow.server.resource;

import io.quarkus.websockets.next.WebSocketConnection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

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

@DisplayName("DashboardWebSocketEndpoint")
class DashboardWebSocketEndpointTest {

    private DashboardWebSocketEndpoint endpoint;
    private WebSocketConnection connection;

    @BeforeEach
    void setUp() {
        endpoint = new DashboardWebSocketEndpoint();
        connection = Mockito.mock(WebSocketConnection.class);
        when(connection.id()).thenReturn("test-connection-id");
    }

    @Test
    @DisplayName("onOpen retourne un message connected")
    void onOpen_returnsConnectedMessage() {
        String result = endpoint.onOpen(connection);
        assertThat(result).contains("connected");
        assertThat(result).contains("UnionFlow Dashboard WebSocket");
    }

    @Test
    @DisplayName("onMessage avec 'ping' retourne pong")
    void onMessage_ping_returnsPong() {
        String result = endpoint.onMessage("ping", connection);
        assertThat(result).contains("pong");
        assertThat(result).contains("timestamp");
    }

    @Test
    @DisplayName("onMessage avec 'PING' majuscules retourne pong")
    void onMessage_pingUppercase_returnsPong() {
        String result = endpoint.onMessage("PING", connection);
        assertThat(result).contains("pong");
    }

    @Test
    @DisplayName("onMessage avec JSON ping retourne pong")
    void onMessage_jsonPing_returnsPong() {
        String result = endpoint.onMessage("{\"type\":\"ping\"}", connection);
        assertThat(result).contains("pong");
    }

    @Test
    @DisplayName("onMessage avec message quelconque retourne ack")
    void onMessage_otherMessage_returnsAck() {
        String result = endpoint.onMessage("hello", connection);
        assertThat(result).contains("ack");
        assertThat(result).contains("received");
    }

    @Test
    @DisplayName("onClose ne lève pas d'exception")
    void onClose_doesNotThrow() {
        endpoint.onClose(connection);
        // pas d'exception attendue
    }

    @Test
    @DisplayName("onMessage avec message vide retourne ack")
    void onMessage_emptyMessage_returnsAck() {
        String result = endpoint.onMessage("", connection);
        assertThat(result).isNotNull();
        assertThat(result).contains("ack");
    }

    @Test
    @DisplayName("onMessage avec null retourne une réponse non nulle")
    void onMessage_nullMessage_returnsNonNull() {
        String result = endpoint.onMessage(null, connection);
        assertThat(result).isNotNull();
    }

    @Test
    @DisplayName("onOpen avec connection id null ne lève pas d'exception")
    void onOpen_connectionIdNull_doesNotThrow() {
        when(connection.id()).thenReturn(null);
        String result = endpoint.onOpen(connection);
        assertThat(result).isNotNull();
        assertThat(result).contains("connected");
    }

    @Test
    @DisplayName("onMessage avec JSON inconnu retourne ack")
    void onMessage_unknownJson_returnsAck() {
        String result = endpoint.onMessage("{\"type\":\"unknown\",\"data\":{}}", connection);
        assertThat(result).isNotNull();
    }
}
