package com.atlassian.bitbucket.key.ssh;

import com.atlassian.bitbucket.audit.AuditEntry;
import com.atlassian.bitbucket.audit.AuditEntryBuilder;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.ssh.SshAccessKey;
import com.atlassian.bitbucket.ssh.SshKey;
import com.atlassian.bitbucket.ssh.event.SshAccessKeyEventConverter;
import com.atlassian.bitbucket.ssh.event.SshAccessKeyGrantedEvent;
import com.atlassian.bitbucket.ssh.event.SshAccessKeyRevokedEvent;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static com.atlassian.bitbucket.JsonTestUtils.assertJsonContains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class SshAccessKeyEventConverterTest {

    private final AuditEntryBuilder builder = new AuditEntryBuilder();
    private final SshAccessKeyEventConverter converter = new SshAccessKeyEventConverter();
    @Mock
    private SshKey key;
    @Mock
    private SshAccessKey keyAccess;
    @Mock
    private Project project;
    @Mock
    private Repository repository;

    @Before
    public void setup() {
        when(key.getId()).thenReturn(1);
        when(key.getLabel()).thenReturn("key-label");
        when(key.getText()).thenReturn("key-text");

        when(keyAccess.getKey()).thenReturn(key);

        when(project.getId()).thenReturn(3);
        when(project.getKey()).thenReturn("project-key");

        when(repository.getId()).thenReturn(4);
        when(repository.getSlug()).thenReturn("repository-slug");
        when(repository.getProject()).thenReturn(project);
    }

    @Test
    public void testAccessGrantedToRepo() {
        mockTarget(repository, Permission.REPO_READ);
        AuditEntry entry = converter.convert(new SshAccessKeyGrantedEvent(this, keyAccess), builder);

        assertEquals(SshAccessKeyGrantedEvent.class.getSimpleName(), entry.getAction());
        assertEquals(repository, entry.getRepository());
        assertEquals(project, entry.getProject());

        String details = entry.getDetails();
        assertJsonContains(details, "permission", "REPO_READ");
        assertJsonContains(details, "key.id", "1");
        assertJsonContains(details, "key.label", "key-label");
        assertJsonContains(details, "repository.id", "4");
        assertJsonContains(details, "repository.slug", "repository-slug");
    }

    @Test
    public void testAccessRevokedFromProject() {
        mockTarget(project, Permission.PROJECT_WRITE);
        AuditEntry entry = converter.convert(new SshAccessKeyRevokedEvent(this, keyAccess), builder);

        assertEquals(SshAccessKeyRevokedEvent.class.getSimpleName(), entry.getAction());
        assertNull(entry.getRepository());
        assertEquals(project, entry.getProject());

        String details = entry.getDetails();
        assertJsonContains(details, "permission", "PROJECT_WRITE");
        assertJsonContains(details, "key.id", "1");
        assertJsonContains(details, "key.label", "key-label");
        assertJsonContains(details, "project.id", "3");
        assertJsonContains(details, "project.key", "project-key");
    }

    private void mockTarget(Object resource, Permission permission) {
        when(keyAccess.getPermission()).thenReturn(permission);
        when(keyAccess.getResource()).thenReturn(resource);
    }
}
