package com.braintree.payment.local.methods.dao.impl;

import com.braintree.enums.BrainTreePaymentMethod;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.model.BraintreeLocalPaymentMethodsModel;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.order.CartModel;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.SearchResult;
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 java.util.Collections;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


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

    private static final String GET_ALL_LOCAL_PAYMENTS =
            "SELECT {" + BraintreeLocalPaymentMethodsModel.PK + "} FROM {" + BraintreeLocalPaymentMethodsModel._TYPECODE
                    + "} WHERE {" + BraintreeLocalPaymentMethodsModel.ISENABLED + "} = ?trueValue";

    private static final String GET_ORDER_BY_PAYMENT_METHOD_NONCE = "SELECT {order:" + OrderModel.PK + "} FROM {"
            + OrderModel._TYPECODE + " as order JOIN " + BrainTreePaymentInfoModel._TYPECODE +
            " as brainTreePaymentInfo" + " ON {order:" + OrderModel.PAYMENTINFO + "} = {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PK + "}} " + "WHERE {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.NONCE + "} = ?nonce";

    private static final String GET_ORDER_BY_PAYMENT_ID = "SELECT {order:" + OrderModel.PK + "} FROM {"
            + OrderModel._TYPECODE + " as order JOIN " + BrainTreePaymentInfoModel._TYPECODE +
            " as brainTreePaymentInfo" + " ON {order:" + OrderModel.PAYMENTINFO + "} = {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PK + "}} " + "WHERE {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PAYMENTID + "} = ?paymentId";

    private static final String GET_CART_BY_PAYMENT_ID = "SELECT {cart:" + CartModel.PK + "} FROM {"
            + CartModel._TYPECODE + " as cart JOIN " + BrainTreePaymentInfoModel._TYPECODE +
            " as brainTreePaymentInfo" + " ON {cart:" + CartModel.PAYMENTINFO + "}={brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PK + "}} " + "WHERE {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PAYMENTID + "} = ?paymentId AND {brainTreePaymentInfo:" +
            BrainTreePaymentInfoModel.PAYMENTPROVIDER + "} = ?paymentProvider";

    private static final String PAYMENT_ID = "testPaymentID";

    @Mock
    protected FlexibleSearchService flexibleSearchService;

    @InjectMocks
    private DefaultBraintreeLocalPaymentMethodsDao unit;

    @Mock
    private SearchResult<BraintreeLocalPaymentMethodsModel> braintreeLocalPaymentMethodsModelSearchResult;

    @Mock
    private SearchResult<OrderModel> orderModelSearchResult;

    @Mock
    private SearchResult<CartModel> cartModelSearchResult;

    @Test
    public void getAllShouldUseExceptedQuery() {
        final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(GET_ALL_LOCAL_PAYMENTS);
        fQuery.addQueryParameter("trueValue", Boolean.TRUE);
        fQuery.setResultClassList(Collections.singletonList(BraintreeLocalPaymentMethodsModel.class));

        when(flexibleSearchService.<BraintreeLocalPaymentMethodsModel>search(fQuery)).thenReturn(braintreeLocalPaymentMethodsModelSearchResult);

        unit.getAll();

        verify(braintreeLocalPaymentMethodsModelSearchResult).getResult();
    }

    @Test
    public void getOrderByPaymentMethodNonceShouldUseExceptedQuery() {
        final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(GET_ORDER_BY_PAYMENT_METHOD_NONCE);
        fQuery.addQueryParameter("nonce", PAYMENT_ID);
        fQuery.setResultClassList(Collections.singletonList(OrderModel.class));

        when(flexibleSearchService.<OrderModel>search(fQuery)).thenReturn(orderModelSearchResult);

        unit.getOrderByPaymentMethodNonce(PAYMENT_ID);

        verify(orderModelSearchResult).getResult();
    }

    @Test
    public void getOrderByPaymentIdShouldUseExceptedQuery() {
        final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(GET_ORDER_BY_PAYMENT_ID);
        fQuery.addQueryParameter("paymentId", PAYMENT_ID);
        fQuery.setResultClassList(Collections.singletonList(OrderModel.class));

        when(flexibleSearchService.<OrderModel>search(fQuery)).thenReturn(orderModelSearchResult);

        unit.getOrderByPaymentId(PAYMENT_ID);

        verify(orderModelSearchResult).getResult();
    }

    @Test
    public void getCarByPaymentIdShouldUseExceptedQuery() {
        final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(GET_CART_BY_PAYMENT_ID);
        fQuery.addQueryParameter("paymentId", PAYMENT_ID);
        fQuery.addQueryParameter("paymentProvider", BrainTreePaymentMethod.LOCALPAYMENT.toString());
        fQuery.setResultClassList(Collections.singletonList(CartModel.class));

        when(flexibleSearchService.<CartModel>search(fQuery)).thenReturn(cartModelSearchResult);

        unit.getCarByPaymentId(PAYMENT_ID);

        verify(cartModelSearchResult).getResult();
    }

}
