package cz.moneta.test.harness.tests.config;

import cz.moneta.test.harness.config.ConfigProvider;
import cz.moneta.test.harness.exception.HarnessConfigurationException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Map;

import static cz.moneta.test.harness.constants.ConstantsForUnitTests.CONFIG_PROPERTY_IDENTIFIER;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class ConfigProviderTest {

    private static final String ANSWER_KEY = "answer";
    private static final String ANSWER_VALUE = "42";

    @Test
    void requiresConfigParameter() {
        Assertions.assertThrows(HarnessConfigurationException.class, ConfigProvider::readConfig,
                "Reading configuration must fail when no config parameter was given and HARNESS_CONFIG is not set");
    }

    @Test
    void looksUpConfigOnClasspath() {
        setSystemConfigProperty("config/simple");
        assertEquals(1, ConfigProvider.readConfig().size());
    }

    @Test
    void looksUpConfigOnClasspathWithReferenceResolution() {
        setSystemConfigProperty("config/references/valid/c");
        Map<String, String> configMap = ConfigProvider.readConfig();
        assertEquals(2, configMap.size());
        assertEquals("config/references/valid/b", configMap.get("environment.from"));
        assertEquals(ANSWER_VALUE, configMap.get(ANSWER_KEY));
    }

    @Test
    void shouldThrowWhenCircularReferencesWereDetected() {
        setSystemConfigProperty("config/references/invalid/c");
        assertThrows(IllegalStateException.class, ConfigProvider::readConfig,
                "Reading configuration with circular dependencies must fail");
    }

    @Test
    void shouldResolveEnvironmentVariable() {
        setSystemConfigProperty("config/with-env");
        System.setProperty("secret.answer", ANSWER_VALUE);
        Map<String, String> config = ConfigProvider.readConfig();
        assertEquals(ANSWER_VALUE, config.get(ANSWER_KEY));
    }

    @Test
    void shouldThrowWhenEnvironmentVariableCannotBeResolved() {
        setSystemConfigProperty("config/with-env-unmapped");
        assertThrows(IllegalStateException.class, ConfigProvider::readConfig,
                "Reading configuration must fail when no config parameter was given");
    }

    @AfterEach
    void cleanUp() {
        System.clearProperty(CONFIG_PROPERTY_IDENTIFIER);
    }

    private void setSystemConfigProperty(String configProperty) {
        System.setProperty(CONFIG_PROPERTY_IDENTIFIER, configProperty); //TODO internal getReaderForClasspathResource add envs/ to path -> FIX
    }
}
