package com.atlassian.bitbucket.mesh.management;

import com.atlassian.bitbucket.mesh.io.MoreFiles;
import com.atlassian.bitbucket.mesh.junit.TemporaryDirectory;
import com.atlassian.bitbucket.mesh.layout.StorageLayout;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;

import static com.atlassian.bitbucket.mesh.layout.StorageLayout.MESH_PROPERTIES;
import static com.atlassian.bitbucket.mesh.management.FileSanitizer.SANITIZER_MESSAGE;
import static com.atlassian.bitbucket.mesh.management.SupportUtils.APPLICATION_PROPERTIES_JSON;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class FileSanitizerTest {

    @Rule
    public final TemporaryDirectory tempDir = new TemporaryDirectory();

    private FileSanitizer fileSanitizer;
    @Mock
    private StorageLayout storageLayout;

    @Before
    public void setup() {
        when(storageLayout.getTempDir()).thenReturn(tempDir.getRoot());
        fileSanitizer = new FileSanitizer(storageLayout.getTempDir());
    }

    @Test
    public void testSanitize() throws IOException {
        Path unsanitizedFile = tempDir.newFile(MESH_PROPERTIES);

        String unsanitizedContent = "node.id=1\n" +
                "node.port=7777\n" +
                "    authentication.token : abcdefg1234\n" +
                "node.name=node-1\n";
        MoreFiles.write(unsanitizedFile, unsanitizedContent);

        Path sanitizedFile = fileSanitizer.sanitize(unsanitizedFile);
        String sanitizedContent = MoreFiles.toString(sanitizedFile);

        assertNotEquals(sanitizedContent, unsanitizedContent);
        assertFalse(sanitizedContent.contains("    authentication.token : abcdefg1234"));
        assertTrue(sanitizedContent.contains("    authentication.token : " + SANITIZER_MESSAGE));
    }

    @Test
    public void testSanitizeLine() {
        assertEquals("-Dlogging.console=true",
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-Dlogging.console=true"));
        assertEquals("-Dpassword=" + SANITIZER_MESSAGE,
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-Dpassword=unknown"));
        assertEquals("-console.password=" + SANITIZER_MESSAGE,
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-console.password=password"));
        assertEquals("-user=" + SANITIZER_MESSAGE,
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-user=Alice"));
        assertEquals("-USER=" + SANITIZER_MESSAGE,
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-USER=bob"));
        assertEquals("-database.user=" + SANITIZER_MESSAGE,
                fileSanitizer.sanitizeLine(APPLICATION_PROPERTIES_JSON, "-database.user=admin"));
    }

    @Test
    public void testSanitizeList() {
        assertThat(fileSanitizer.sanitizeList(APPLICATION_PROPERTIES_JSON,
                ImmutableList.of("-USER=bob", "-Dpassword=unknown", "all=good")),
                hasItems("-USER=" + SANITIZER_MESSAGE, "-Dpassword=" + SANITIZER_MESSAGE, "all=good"));
    }

    @Test
    public void testSanitizeMap() {
        Map<String, String> sanitizedMap =
                fileSanitizer.sanitizeMap(ImmutableMap.of("good", "value", "password", "ABCDDE1234", "user", "db_admin"));
        assertThat(sanitizedMap, hasEntry("good", "value"));
        assertThat(sanitizedMap, hasEntry("password", SANITIZER_MESSAGE));
        assertThat(sanitizedMap, hasEntry("user", SANITIZER_MESSAGE));
    }

    @Test
    public void testSanitizeValue() {
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("password", "ABCDE"));
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("user", "alice"));
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("User", "bob"));
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("PassWord", "1234"));
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("User_Name", "charlie"));
        assertEquals(SANITIZER_MESSAGE, fileSanitizer.sanitizeValue("Database_Password", "db_pw"));

        assertEquals("value", fileSanitizer.sanitizeValue("home", "value"));
        assertEquals("another", fileSanitizer.sanitizeValue("word", "another"));
        assertEquals("variable", fileSanitizer.sanitizeValue("environment", "variable"));
    }
}