/*
 * Copyright (c) 2024. Das Land Schleswig-Holstein vertreten durch das Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
 * Zentrales IT-Management
 *
 * Lizenziert unter der EUPL, Version 1.2 oder - sobald
 * diese von der Europäischen Kommission genehmigt wurden -
 * Folgeversionen der EUPL ("Lizenz");
 * Sie dürfen dieses Werk ausschließlich gemäß
 * dieser Lizenz nutzen.
 * Eine Kopie der Lizenz finden Sie hier:
 *
 * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 *
 * Sofern nicht durch anwendbare Rechtsvorschriften
 * gefordert oder in schriftlicher Form vereinbart, wird
 * die unter der Lizenz verbreitete Software "so wie sie
 * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
 * ausdrücklich oder stillschweigend - verbreitet.
 * Die sprachspezifischen Genehmigungen und Beschränkungen
 * unter der Lizenz sind dem Lizenztext zu entnehmen.
 */
package de.ozgcloud.admin.security;

import static de.ozgcloud.admin.security.SecurityConfiguration.*;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.springframework.security.oauth2.jwt.Jwt;

import de.ozgcloud.admin.environment.OAuth2Properties;

class SecurityConfigurationTest {

	@Spy
	@InjectMocks
	private SecurityConfiguration securityConfiguration;
	@Mock
	private AdminAuthenticationEntryPoint authenticationEntryPoint;

	@Mock
	private OAuth2Properties oAuth2Properties;

	@DisplayName("get keycloak roles from jwt")
	@Nested
	class TestGetKeycloakRolesFromJwt {

		@BeforeEach
		void mock() {
			lenient().when(oAuth2Properties.getResource()).thenReturn(JwtTestFactory.AUTH_RESOURCE);
		}

		@DisplayName("should return empty list if resource_access.admin.roles path is missing")
		@ParameterizedTest
		@MethodSource("getIncompleteJwt")
		void shouldReturnEmptyListIfResourceAccessAdminRolesPathIsMissing(Jwt incompleteJwt) {
			var roleStrings = securityConfiguration.getKeycloakRolesFromJwt(incompleteJwt);

			assertThat(roleStrings).isEmpty();
		}

		private static Stream<Arguments> getIncompleteJwt() {
			return Stream.of(JwtTestFactory.create(),
							JwtTestFactory.createBuilder().claim(RESOURCE_ACCESS_KEY, Map.of()).build(),
							JwtTestFactory.createBuilder().claim(RESOURCE_ACCESS_KEY, Map.of("admin", Map.of())).build(),
							JwtTestFactory.createWithRoles(emptyList()).build())
					.map(Arguments::of);
		}

		@DisplayName("should return resource_access.admin.roles list")
		@Test
		void shouldReturnResourceAccessAdminRolesList() {
			var expectedRoles = List.of(JwtTestFactory.ROLE_1, JwtTestFactory.ROLE_2, JwtTestFactory.ROLE_3);
			var jwtWithRoles = JwtTestFactory.createWithRoles(expectedRoles).build();

			var roleStrings = securityConfiguration.getKeycloakRolesFromJwt(jwtWithRoles);

			assertThat(roleStrings).isEqualTo(expectedRoles);
		}

	}
}