package com.braintree.service;

import com.braintree.daos.BrainTreeAccessTokenDao;
import com.braintree.model.PaypalAccessTokenModel;
import com.braintree.service.impl.DefaultBraintreeAccessTokenService;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.commerceservices.util.GuidKeyGenerator;
import de.hybris.platform.servicelayer.model.ModelService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Optional;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.any;

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

    private static final String ID = "ID";
    private static final String TOKEN = "TOKEN";

    @Mock
    private PaypalAccessTokenModel accessTokenModel;

    @Mock
    private BrainTreeAccessTokenDao braintreeAccessTokenDao;
    @Mock
    private GuidKeyGenerator guidKeyGenerator;
    @Mock
    private ModelService modelService;

    @Spy
    @InjectMocks
    private DefaultBraintreeAccessTokenService unit;

    @Test
    public void shouldGetPaypalAccessToken() {
        final Optional<PaypalAccessTokenModel> optionalAccessTokenModel = Optional.of(accessTokenModel);

        when(braintreeAccessTokenDao.findAccessTokenByGuid(ID)).thenReturn(optionalAccessTokenModel);

        final Optional<PaypalAccessTokenModel> result = unit.getPaypalAccessToken(ID);

        assertEquals(optionalAccessTokenModel, result);
    }

    @Test
    public void shouldSavePaypalAccessToken() {
        when(guidKeyGenerator.generate()).thenReturn(ID);
        doNothing().when(modelService).save(any(PaypalAccessTokenModel.class));

        final String result = unit.savePaypalAccessToken(TOKEN);

        assertEquals(ID, result);
        verify(guidKeyGenerator).generate();
        verify(modelService).save(any(PaypalAccessTokenModel.class));
    }

    @Test
    public void shouldRemovePaypalAccessToken() {
        final Optional<PaypalAccessTokenModel> optionalAccessTokenModel = Optional.of(accessTokenModel);

        doReturn(optionalAccessTokenModel).when(unit).getPaypalAccessToken(ID);
        doNothing().when(modelService).remove(accessTokenModel);

        unit.removePaypalAccessToken(ID);

        verify(unit).getPaypalAccessToken(ID);
        verify(modelService).remove(accessTokenModel);
    }

    @Test
    public void shouldNotRemovePaypalAccessToken() {
        final Optional<PaypalAccessTokenModel> optionalAccessTokenModel = Optional.empty();

        doReturn(optionalAccessTokenModel).when(unit).getPaypalAccessToken(ID);

        unit.removePaypalAccessToken(ID);

        verify(unit).getPaypalAccessToken(ID);
        verify(modelService, never()).remove(any(PaypalAccessTokenModel.class));
    }

}
