package com.braintree.transaction.dao.impl;

import com.braintree.enums.BraintreePaymentTransactionStatus;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.servicelayer.data.SearchPageData;
import de.hybris.platform.payment.model.PaymentTransactionModel;
import de.hybris.platform.servicelayer.exceptions.ModelNotFoundException;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.paginated.PaginatedFlexibleSearchParameter;
import de.hybris.platform.servicelayer.search.paginated.PaginatedFlexibleSearchService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.ArrayList;
import java.util.List;

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

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

    private static final String GET_TRANSACTION_BY_TRANSACTION_ID = "select {" + PaymentTransactionModel.PK
            + "} FROM {" + PaymentTransactionModel._TYPECODE + "} where {" +
            PaymentTransactionModel.REQUESTID + "} = ?transactionId";

    private static final String TRANSACTION_ID = "transactionId";
    private static final String TRANSACTION_ID_VALUE = "transaction id value";
    private static final String TRANSACTION_ID_NOT_EXISTING_VALUE = "transaction id not existing value";
    private static final String TRANSACTION_STATUSES = "transactionStatuses";
    @Mock
    private FlexibleSearchService flexibleSearchService;
    @Mock
    private PaginatedFlexibleSearchService paginatedFlexibleSearchService;
    @Captor
    private ArgumentCaptor<FlexibleSearchQuery> flexibleSearchQueryArgumentCaptor;
    @Captor
    private ArgumentCaptor<PaginatedFlexibleSearchParameter> paginatedFlexibleSearchQueryArgumentCaptor;

    @InjectMocks
    private DefaultBraintreeTransactionDAO unit;

    @Test
    public void shouldCallPaginatedFlexibleSearchServiceWithParameters() {
        final List<BraintreePaymentTransactionStatus> statuses = mock(ArrayList.class);
        final SearchPageData<PaymentTransactionModel> searchPage = mock(SearchPageData.class);

        unit.getPaymentTransactionsByStatuses(statuses, searchPage);

        verify(paginatedFlexibleSearchService).search(paginatedFlexibleSearchQueryArgumentCaptor.capture());

        PaginatedFlexibleSearchParameter value = paginatedFlexibleSearchQueryArgumentCaptor.getValue();
        assertEquals(statuses, value.getFlexibleSearchQuery().getQueryParameters().get(TRANSACTION_STATUSES));
        assertEquals(searchPage, value.getSearchPageData());
    }

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionWhenParameterIsNull() {
        unit.findTransactionByTransactionId(null);
    }

    @Test
    public void shouldFindTransactionWhenItExists() {
        unit.findTransactionByTransactionId(TRANSACTION_ID_VALUE);

        verify(flexibleSearchService).searchUnique(flexibleSearchQueryArgumentCaptor.capture());

        FlexibleSearchQuery flexibleSearchQuery = flexibleSearchQueryArgumentCaptor.getValue();
        assertFalse(flexibleSearchQuery.getQueryParameters().isEmpty());
        assertEquals(TRANSACTION_ID_VALUE, flexibleSearchQuery.getQueryParameters().get(TRANSACTION_ID));
        assertEquals(GET_TRANSACTION_BY_TRANSACTION_ID, flexibleSearchQuery.getQuery());
    }

    @Test(expected = ModelNotFoundException.class)
    public void shouldNotFindTransactionWhenItDoesNotExist() {
        when(flexibleSearchService.searchUnique(any(FlexibleSearchQuery.class))).thenThrow(ModelNotFoundException.class);

        unit.findTransactionByTransactionId(TRANSACTION_ID_NOT_EXISTING_VALUE);
    }

}
