/*
 * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
 * Ministerpräsidenten des Landes Schleswig-Holstein
 * Staatskanzlei
 * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 *
 * 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;

import static de.ozgcloud.admin.RootModelAssembler.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

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.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestProperties;
import org.springframework.hateoas.IanaLinkRelations;
import org.springframework.hateoas.Link;

import com.thedeanda.lorem.LoremIpsum;

import de.ozgcloud.admin.common.user.CurrentUserService;

class RootModelAssemblerTest {

	private static final String BASE_PATH = "/api/base";

	@Spy
	@InjectMocks
	private RootModelAssembler modelAssembler;

	@Mock
	private RepositoryRestProperties restProperties;
	@Mock
	private CurrentUserService currentUserService;
	@Mock
	private DocumentationProperties documentationProperties;

	@DisplayName("Entity Model")
	@Nested
	class TestToModel {

		private final Root root = RootTestFactory.create();

		@Test
		void shouldHaveRootContent() {
			var resultRoot = modelAssembler.toModel(root).getContent();

			assertThat(resultRoot).isEqualTo(root);
		}

		@Test
		void shouldHaveSelfLink() {
			var model = modelAssembler.toModel(root);

			assertThat(model.getLink(IanaLinkRelations.SELF)).get().extracting(Link::getHref).isEqualTo(RootController.PATH);
		}

		@Nested
		class TestConfigurationLink {

			@Test
			void shouldCallHasConfigurationPermission() {
				modelAssembler.toModel(root);

				verify(currentUserService).hasConfigurationPermission();
			}

			@Nested
			class TestOnHasConfigurationPermission {

				@BeforeEach
				void mock() {
					when(currentUserService.hasConfigurationPermission()).thenReturn(true);
					when(restProperties.getBasePath()).thenReturn(BASE_PATH);
				}

				@Test
				void shouldHaveHrefToConfiguration() {
					var model = modelAssembler.toModel(root);

					assertThat(model.getLink(REL_CONFIGURATION)).get().extracting(Link::getHref).isEqualTo(BASE_PATH);
				}
			}

			@Nested
			class TestOnHasNotConfigurationPermission {

				@BeforeEach
				void mock() {
					when(currentUserService.hasConfigurationPermission()).thenReturn(false);
				}

				@Test
				void shouldNotHaveConfigurationLink() {
					var model = modelAssembler.toModel(root);

					assertThat(model.getLink(REL_CONFIGURATION)).isEmpty();
				}
			}
		}

		@Nested
		class TestDocumentationLink {

			@Test
			void shouldGetDocumentationUrl() {
				modelAssembler.toModel(root);

				verify(documentationProperties).getUrl();
			}

			@Nested
			class TestOnDocumentationUrlGiven {

				private final String documentationUrl = LoremIpsum.getInstance().getUrl();

				@BeforeEach
				void mock() {
					when(documentationProperties.getUrl()).thenReturn(documentationUrl);
				}

				@Test
				void shouldHaveDocumentationLink() {
					var model = modelAssembler.toModel(root);

					assertThat(model.getLink(REL_DOCUMENTATIONS)).get().extracting(Link::getHref).isEqualTo(documentationUrl);
				}
			}

			@Nested
			class TestOnDocumentationUrlNotGiven {

				@BeforeEach
				void mock() {
					when(documentationProperties.getUrl()).thenReturn(null);
				}

				@Test
				void shouldNotHaveDocumentationLink() {
					var model = modelAssembler.toModel(root);

					assertThat(model.getLink(REL_DOCUMENTATIONS)).isEmpty();
				}
			}
		}
	}
}