package dk.sample.rest.bank.customer.exposure.rs;


import dk.sample.rest.bank.customer.persistence.CustomerArchivist;
import dk.sample.rest.bank.customer.exposure.rs.model.EventRepresentation;
import dk.sample.rest.bank.customer.model.Event;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import dk.sample.rest.bank.customer.exposure.rs.model.EventsRepresentation;
import dk.sample.rest.common.test.rs.UriBuilderFactory;
import dk.nykredit.time.CurrentTime;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

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

@RunWith(MockitoJUnitRunner.class)
public class CustomerEventServiceExposureTest {

    @Mock
    CustomerArchivist archivist;

    @InjectMocks
    CustomerEventServiceExposure service;

    @Test
    public void testListEvents() throws URISyntaxException {
        UriInfo ui = mock(UriInfo.class);
        when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock")));

        Request request = mock(Request.class);

        List<Event> eventList = new ArrayList<>(3);
        eventList.add(new Event(new URI("customers/default/eventSID"),
                "default", CurrentTime.now()));
        eventList.add(new Event(new URI("customers/1234567890/cards"),
                "black-card", CurrentTime.now()));
        eventList.add(new Event(new URI("customers/1234567890/accounts"),
                "additional-account", CurrentTime.nowAsZonedDateTime().minusDays(1).toInstant()));

        when(archivist.findEvents(Optional.empty()))
                .thenReturn(eventList);

        Response response = service.listAllCustomerEvents(ui, request, "application/hal+json", "");
        EventsRepresentation events = (EventsRepresentation) response.getEntity();

        assertEquals(3, events.getEvents().size());
        assertEquals("http://mock/customer-events", events.getSelf().getHref());

        Collection<EventRepresentation> ers = events.getEvents();
        int found = 0;
        for (EventRepresentation eventRepresentation : ers) {
            if("default".equals(eventRepresentation.getCategory())) {
                assertEquals("http://mock/customers/default/eventSID", eventRepresentation.getOrigin().getHref());
                assertEquals("default", eventRepresentation.getCategory());
                assertEquals("http://mock/customer-events/default/" + eventRepresentation.getId(), eventRepresentation.getSelf().getHref());
                found++;
            }
            if("black-card".equals(eventRepresentation.getCategory())) {
                assertEquals("http://mock/customers/1234567890/cards", eventRepresentation.getOrigin().getHref());
                assertEquals("black-card", eventRepresentation.getCategory());
                assertEquals("http://mock/customer-events/black-card/" + eventRepresentation.getId(), eventRepresentation.getSelf().getHref());
                found++;
            }
            if("additional-account".equals(eventRepresentation.getCategory())) {
                assertEquals("http://mock/customers/1234567890/accounts", eventRepresentation.getOrigin().getHref());
                assertEquals("additional-account", eventRepresentation.getCategory());
                assertEquals("http://mock/customer-events/additional-account/" +  eventRepresentation.getId(), eventRepresentation.getSelf().getHref());
                found++;
            }
        }
        assertEquals(3, found);

        response = service.listAllCustomerEvents(ui, request, "application/hal+json;no-real-type", "");
        assertEquals(415,response.getStatus());

    }

    @Test
    public void testListEventsByCategory() throws URISyntaxException {
        UriInfo ui = mock(UriInfo.class);
        when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock")));

        Request request = mock(Request.class);

        when(archivist.getEventsForCategory(Event.getCategory("some", "category"), Optional.empty()))
                .thenReturn(Collections.singletonList(new Event(new URI("customer-events/some-category/eventSID"),
                        "some-category", CurrentTime.now())));

        Response response = service.getCustomerEventsByCategory(ui, request, "application/hal+json", "some-category", "");
        EventsRepresentation events = (EventsRepresentation) response.getEntity();

        assertEquals(1, events.getEvents().size());
        assertEquals("http://mock/customer-events", events.getSelf().getHref());

        response = service.getCustomerEventsByCategory(ui, request, "application/hal+json;no-real-type", "some-category", "");
        assertEquals(415,response.getStatus());
    }

    @Test
    public void testGetEvent() throws URISyntaxException {
        UriInfo ui = mock(UriInfo.class);
        when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock")));

        Request request = mock(Request.class);

        when(archivist.getEvent("new-card","eventSID"))
                .thenReturn(new Event(new URI("customers/1010101010/cards")));

        Response response = service.getSingleCustomerEvents(ui, request, "application/hal+json", "new-card", "eventSID");
        EventRepresentation er = (EventRepresentation) response.getEntity();

        assertEquals("default", er.getCategory());
        assertEquals("http://mock/customer-events/default/" + er.getId(), er.getSelf().getHref());
        assertEquals("http://mock/customers/1010101010/cards", er.getOrigin().getHref());

        response = service.getSingleCustomerEvents(ui, request, "application/hal+json;no-real-type", "5479-123456", "eventSID");
        assertEquals(415,response.getStatus());

    }

}