package dev.lions.unionflow.server.client;

import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.Tokens;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.ServiceUnavailableException;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
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 static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class AdminServiceTokenHeadersFactoryTest {

    @Mock
    OidcClient adminOidcClient;

    private AdminServiceTokenHeadersFactory factory;

    @BeforeEach
    void setUp() throws Exception {
        factory = new AdminServiceTokenHeadersFactory();

        Field clientField = AdminServiceTokenHeadersFactory.class.getDeclaredField("adminOidcClient");
        clientField.setAccessible(true);
        clientField.set(factory, adminOidcClient);
    }

    @Test
    void update_whenTokensObtained_addsAuthorizationHeader() {
        Tokens tokens = mock(Tokens.class);
        when(tokens.getAccessToken()).thenReturn("service-account-token-xyz");
        when(adminOidcClient.getTokens()).thenReturn(Uni.createFrom().item(tokens));

        MultivaluedMap<String, String> incoming = new MultivaluedHashMap<>();
        MultivaluedMap<String, String> outgoing = new MultivaluedHashMap<>();

        MultivaluedMap<String, String> result = factory.update(incoming, outgoing);

        assertThat(result.getFirst("Authorization")).isEqualTo("Bearer service-account-token-xyz");
    }

    @Test
    void update_whenOidcClientFails_throwsServiceUnavailableException() {
        when(adminOidcClient.getTokens()).thenReturn(
                Uni.createFrom().failure(new RuntimeException("Keycloak unreachable")));

        MultivaluedMap<String, String> incoming = new MultivaluedHashMap<>();
        MultivaluedMap<String, String> outgoing = new MultivaluedHashMap<>();

        assertThatThrownBy(() -> factory.update(incoming, outgoing))
                .isInstanceOf(ServiceUnavailableException.class)
                .hasMessageContaining("authentification");
    }

    @Test
    void update_whenOidcClientReturnsNullToken_stillAddsHeader() {
        Tokens tokens = mock(Tokens.class);
        when(tokens.getAccessToken()).thenReturn("");
        when(adminOidcClient.getTokens()).thenReturn(Uni.createFrom().item(tokens));

        MultivaluedMap<String, String> incoming = new MultivaluedHashMap<>();
        MultivaluedMap<String, String> outgoing = new MultivaluedHashMap<>();

        MultivaluedMap<String, String> result = factory.update(incoming, outgoing);

        assertThat(result.getFirst("Authorization")).isEqualTo("Bearer ");
    }
}
