package com.braintree.order.dao.impl;

import com.braintree.model.BrainTreePaymentInfoModel;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.PK;
import de.hybris.platform.core.enums.OrderStatus;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.SearchResult;
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 static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any;


@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class DefaultBrainTreeOrderDaoTest {
    private static final String BASE_QUERY_LEADING =
            "SELECT COUNT({" + OrderModel.PK + "}) " +
                    "FROM {" + OrderModel._TYPECODE + " AS order " +
                    "JOIN " + BrainTreePaymentInfoModel._TYPECODE + " AS pm " +
                    "ON {order:" + OrderModel.PAYMENTINFO + "}={pm:" + BrainTreePaymentInfoModel.PK + "} }" +
                    "WHERE {order:" + OrderModel.STATUS + "} IS NULL OR ({order:" + OrderModel.STATUS +"} <> ?status ";
    private static final String BASE_QUERY_PAYMENT_INFO_MODEL =
            "AND {pm:" + BrainTreePaymentInfoModel.ORIGINAL + "} = ?paymentId ";
    private static final String BASE_QUERY_CUSTOMER_MODEL = "AND {pm:user}=?currentUser ";
    private static final String BASE_QUERY_ENDING =
            "AND {order:" + OrderModel.CREATIONTIME + "} >= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ?expirationDays DAY))";

    private static final String PAYMENT_ID = "paymentId";
    private static final String CURRENT_USER = "currentUser";
    private static final String EXPIRATION_DAYS = "expirationDays";
    private static final String STATUS = "status";
    private static final String Pk = "12345678";
    private static final int EXPIRATION = 30;

    @Mock
    private BrainTreePaymentInfoModel paymentInfoModel;
    @Mock
    private CustomerModel customerModel;
    @Mock
    private SearchResult searchResult;

    @Mock
    private FlexibleSearchService flexibleSearchService;

    @Captor
    private ArgumentCaptor<FlexibleSearchQuery> flexibleSearchQueryArgumentCaptor;

    @InjectMocks
    private DefaultBrainTreeOrderDao unit;

    @Test
    public void shouldCheckQueryAndParameterForCountAllOrdersWithExpiredTransactions() {
        when(paymentInfoModel.getPk()).thenReturn(PK.parse(Pk));
        when(flexibleSearchService.search(any(FlexibleSearchQuery.class))).thenReturn(searchResult);

        unit.countAllOrdersWithExpiredTransactions(paymentInfoModel, EXPIRATION);

        verify(flexibleSearchService).search(flexibleSearchQueryArgumentCaptor.capture());
        FlexibleSearchQuery flexibleSearchQuery = flexibleSearchQueryArgumentCaptor.getValue();

        assertEquals(BASE_QUERY_LEADING + BASE_QUERY_PAYMENT_INFO_MODEL + BASE_QUERY_ENDING, flexibleSearchQuery.getQuery());
        assertEquals(flexibleSearchQuery.getQueryParameters().get(PAYMENT_ID), PK.parse(Pk));
        assertEquals(flexibleSearchQuery.getQueryParameters().get(EXPIRATION_DAYS), EXPIRATION);
        assertEquals(flexibleSearchQuery.getQueryParameters().get(STATUS), OrderStatus.COMPLETED);
    }

    @Test
    public void shouldCheckQueryAndParameterForCountOrdersWithExpiredTransactionsByCustomer() {
        when(flexibleSearchService.search(any(FlexibleSearchQuery.class))).thenReturn(searchResult);

        unit.countOrdersWithExpiredTransactionsByCustomer(customerModel, EXPIRATION);

        verify(flexibleSearchService).search(flexibleSearchQueryArgumentCaptor.capture());
        FlexibleSearchQuery flexibleSearchQuery = flexibleSearchQueryArgumentCaptor.getValue();

        assertEquals(BASE_QUERY_LEADING + BASE_QUERY_CUSTOMER_MODEL + BASE_QUERY_ENDING, flexibleSearchQuery.getQuery());
        assertEquals(flexibleSearchQuery.getQueryParameters().get(CURRENT_USER), customerModel);
        assertEquals(flexibleSearchQuery.getQueryParameters().get(EXPIRATION_DAYS), EXPIRATION);
        assertEquals(flexibleSearchQuery.getQueryParameters().get(STATUS), OrderStatus.COMPLETED);
    }

}
