package com.braintree.populators;

import com.braintree.hybris.data.BrainTreeGraphQLCustomerData;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeCustomer;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeCustomerConnection;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeCustomerConnectionEdge;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePageInfo;
import com.braintree.hybris.data.graphql.commands.response.BraintreePaymentMethodData;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodConnection;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodConnectionEdge;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.model.BraintreeCustomerDetailsModel;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.servicelayer.dto.converter.Converter;
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.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

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

    private static final String END_CURSOR = "EndCursor";
    private static final String LEGACY_ID = "LegacyId";
    private static final String ID = "Id";
    private static final String COMPANY = "Company";
    private static final String EMAIL = "Email";
    private static final String FIRST_NAME = "User";
    private static final String LAST_NAME = "Tester";
    private static final String PHONE_NUMBER = "+8888888888";

    @InjectMocks
    @Spy
    private BraintreeGraphQLCustomerPopulator unit;

    @Mock
    private BrainTreeCustomerConnection customerConnection;
    @Mock
    private BrainTreePageInfo pageInfo;
    @Mock
    private List<BrainTreeCustomerConnectionEdge> edgeList;
    @Mock
    private Iterator<BrainTreeCustomerConnectionEdge> edgeIterator;
    @Mock
    private BrainTreeCustomerConnectionEdge edge;
    @Mock
    private BrainTreeCustomer customerNode;
    @Mock
    private Calendar calendar;
    @Mock
    private BrainTreePaymentInfoModel paymentInfoModel;
    @Mock
    private Converter<BraintreePaymentMethodData, BrainTreePaymentInfoModel> graphQLPaymentMethodToModel;
    @Mock
    private List<BrainTreePaymentMethodConnectionEdge> paymentMethodConnectionEdgeList;
    @Mock
    private BrainTreePaymentMethodConnectionEdge paymentMethodConnectionEdge;
    @Mock
    private BrainTreePaymentMethodConnection paymentMethodConnection;
    @Mock
    private BraintreePaymentMethodData paymentMethodNode;

    @Test
    public void shouldPopulateCustomerConnectionToCustomerData() {
        BrainTreeGraphQLCustomerData target = new BrainTreeGraphQLCustomerData();

        when(customerConnection.getPageInfo()).thenReturn(pageInfo);
        when(pageInfo.isHasNextPage()).thenReturn(true);
        when(pageInfo.getEndCursor()).thenReturn(END_CURSOR);
        when(customerConnection.getEdges()).thenReturn(edgeList);
        when(edgeList.iterator()).thenReturn(edgeIterator);
        when(edgeIterator.hasNext()).thenReturn(true, false);
        when(edgeIterator.next()).thenReturn(edge);
        when(edge.getNode()).thenReturn(customerNode);
        when(customerNode.getLegacyId()).thenReturn(LEGACY_ID);
        when(customerNode.getId()).thenReturn(ID);
        when(customerNode.getCompany()).thenReturn(COMPANY);
        when(customerNode.getCreatedAt()).thenReturn(calendar);
        when(customerNode.getEmail()).thenReturn(EMAIL);
        when(customerNode.getFirstName()).thenReturn(FIRST_NAME);
        when(customerNode.getLastName()).thenReturn(LAST_NAME);
        when(customerNode.getPhoneNumber()).thenReturn(PHONE_NUMBER);
        when(customerNode.getPaymentMethods()).thenReturn(paymentMethodConnection);
        when(paymentMethodConnection.getEdges()).thenReturn(paymentMethodConnectionEdgeList);
        when(paymentMethodConnectionEdgeList.stream()).thenReturn(Stream.of(paymentMethodConnectionEdge));
        when(paymentMethodConnectionEdge.getNode()).thenReturn(paymentMethodNode);
        when(graphQLPaymentMethodToModel.convert(paymentMethodNode)).thenReturn(paymentInfoModel);

        unit.populate(customerConnection, target);

        assertTrue(target.getHasNextPage());
        assertEquals(END_CURSOR, target.getEndCursor());
        BraintreeCustomerDetailsModel customerDetailsModel = target.getCustomerList().get(0);
        assertEquals(COMPANY, customerDetailsModel.getCompany());
        assertEquals(ID, customerDetailsModel.getGraphQLId());
        assertEquals(LEGACY_ID, customerDetailsModel.getId());
        assertEquals(calendar.getTime(), customerDetailsModel.getCreatedAt());
        assertEquals(EMAIL, customerDetailsModel.getEmail());
        assertEquals(FIRST_NAME, customerDetailsModel.getFirstName());
        assertEquals(LAST_NAME, customerDetailsModel.getLastName());
        assertEquals(PHONE_NUMBER, customerDetailsModel.getPhone());
        assertEquals(paymentInfoModel, customerDetailsModel.getPaymentMethods().get(0));
    }
}