package com.braintree.commands.impl;

import com.braintree.configuration.service.BrainTreeConfigService;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.payment.AdapterException;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import com.braintree.hybris.data.BrainTreeConnectWithPayPalUserData;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import org.springframework.http.HttpEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class DefaultBrainTreeConnectWithPayPalGetUserInformationCommandTest {

    private static final String ACCESS_TOKEN = "accessToken";
    private static final String USER_INFO_ENDPOINT_URL = "identity/oauth2/userinfo?schema=paypalv1.1";
    private static final String API_URL = "http://api.example.com";

    @Mock
    private RestTemplate restTemplate;

    @Mock
    private BrainTreeConfigService mockConfigService;

    @InjectMocks
    private DefaultBrainTreeConnectWithPayPalGetUserInformationCommand getUserInformationCommand;

    @Before
    public void setUp() {
        when(mockConfigService.getPayPalApiUrl()).thenReturn(API_URL);
    }

    @Test
    public void shouldReturnUserDataOnSuccessfulRequest() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(ACCESS_TOKEN);
        HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(headers);
        BrainTreeConnectWithPayPalUserData mockUserData = new BrainTreeConnectWithPayPalUserData();
        ResponseEntity<BrainTreeConnectWithPayPalUserData> mockResponse = new ResponseEntity<>(mockUserData, HttpStatus.OK);

        when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class)))
                .thenReturn(mockResponse);

        BrainTreeConnectWithPayPalUserData result = getUserInformationCommand.perform(ACCESS_TOKEN);

        verify(restTemplate).exchange(API_URL + USER_INFO_ENDPOINT_URL, HttpMethod.GET, httpEntity, BrainTreeConnectWithPayPalUserData.class);
        assertEquals(mockUserData, result);
    }

    @Test(expected = AdapterException.class)
    public void shouldThrowAdapterExceptionOnRequestFailure() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(ACCESS_TOKEN);
        HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(headers);

        when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class)))
                .thenThrow(new RuntimeException("Some error occurred during request"));

        getUserInformationCommand.perform(ACCESS_TOKEN);
    }
}
