package com.atlassian.bitbucket.internal.mirroring.mirror.client;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.internal.mirroring.mirror.MirroringConfig;
import com.atlassian.bitbucket.internal.mirroring.mirror.jwt.JwtSignedRequestFactory;
import com.atlassian.bitbucket.internal.mirroring.mirror.nav.MirroringNavBuilder;
import com.atlassian.bitbucket.internal.mirroring.ssh.encoding.PublicKeyEncodingHelper;
import com.atlassian.bitbucket.json.JsonRenderer;
import com.atlassian.bitbucket.mirroring.mirror.UpstreamServer;
import com.atlassian.bitbucket.mirroring.mirror.client.UpstreamClient;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import com.atlassian.httpclient.api.HttpClient;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.xml.validation.Validator;

import static com.atlassian.bitbucket.mirroring.mirror.UpstreamServerType.BITBUCKET_CLOUD;
import static com.atlassian.bitbucket.mirroring.mirror.UpstreamServerType.BITBUCKET_SERVER;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class DefaultUpstreamClientFactoryTest {
    public static final String SERVER_ID = "server-id";

    @Mock
    private MirroringConfig config;
    @Mock
    private HttpClient httpClient;
    @Mock
    private I18nService i18nService;
    @Mock
    JsonRenderer jsonRenderer;
    @Mock
    JwtSignedRequestFactory jwtSignedRequestFactory;
    @Mock
    MirroringNavBuilder mirroringNavBuilder;
    @Mock
    ApplicationPropertiesService propertiesService;
    @Mock
    PublicKeyEncodingHelper publicKeyHelper;
    @Mock
    Validator validator;
    @InjectMocks
    DefaultUpstreamClientFactory factory;

    @Before
    public void setUp() throws Exception {
        when(propertiesService.getServerId()).thenReturn(SERVER_ID);
    }

    @Test
    public void testCreateForCloudWithCloudUpstream() throws Exception {
        UpstreamServer cloudUpstream = mock(UpstreamServer.class);
        when(cloudUpstream.getType()).thenReturn(BITBUCKET_CLOUD);

        assertNotNull(factory.createForCloud(cloudUpstream));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testCreateForCloudWithServerUpstream() throws Exception {
        UpstreamServer cloudUpstream = mock(UpstreamServer.class);
        when(cloudUpstream.getType()).thenReturn(BITBUCKET_SERVER);

        factory.createForCloud(cloudUpstream);
    }

    @Test
    public void testCreateForServerWithServerUpstream() throws Exception {
        UpstreamServer serverUpstream = mock(UpstreamServer.class);
        when(serverUpstream.getType()).thenReturn(BITBUCKET_SERVER);

        assertNotNull(factory.createForServer(serverUpstream));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testCreateForServerWithCloudUpstream() throws Exception {
        UpstreamServer cloudUpstream = mock(UpstreamServer.class);
        when(cloudUpstream.getType()).thenReturn(BITBUCKET_CLOUD);

        factory.createForServer(cloudUpstream);
    }

    @Test
    public void testCreateWithCloudUpstream() throws Exception {
        UpstreamServer cloudUpstream = mock(UpstreamServer.class);
        when(cloudUpstream.getType()).thenReturn(BITBUCKET_CLOUD);

        UpstreamClient client = factory.create(cloudUpstream);
        assertNotNull(client);
        assertTrue(client instanceof CloudUpstreamClient);
    }

    @Test
    public void testCreateWithServerUpstream() throws Exception {
        UpstreamServer cloudUpstream = mock(UpstreamServer.class);
        when(cloudUpstream.getType()).thenReturn(BITBUCKET_SERVER);

        UpstreamClient client = factory.create(cloudUpstream);
        assertNotNull(client);
        assertTrue(client instanceof ServerUpstreamClient);
    }
}