/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.ei.ui.ws.rs.application.execution;

import static org.mockito.Mockito.when;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Application;

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;

import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.beans.domain.model.receipt.Receipt;
import com.scytl.products.ov.commons.beans.exceptions.ApplicationException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.ApplicationExceptionHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.ResourceNotFoundExceptionHandler;
import com.scytl.products.ov.commons.util.HttpRequestService;
import com.scytl.products.ov.ei.services.domain.service.vote.VoteService;

public class ReceiptResourceTest extends JerseyTest {

    public static final String SIGNATURE = "signature";

    public static final String VALUE = "value";

    ReceiptResource sut;

    private static final String PATH =
        "/receipts/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}";

    @Mock
    HttpServletRequest servletRequest;

    @Mock
    Logger logger;

    @Mock
    TrackIdInstance trackIdInstance;

    @Mock
    HttpRequestService httpRequestService;

    @Mock
    VoteService voteService;

    @Mock
    TransactionInfoProvider transactionInfoProvider;

    private static String tenantId = "100";

    private static String electionEventId = "100";

    private static String votingCardId = "100";

    @Test
    public void getReceipt() throws ResourceNotFoundException, ApplicationException {

        int expectedStatus = 200;

        commonPreparation();

        Receipt receipt = new Receipt();
        receipt.setSignature(SIGNATURE);
        receipt.setReceipt(VALUE);

        when(voteService.getVoteReceipt(tenantId, electionEventId, votingCardId)).thenReturn(receipt);

        int status = executeRequest();

        Assert.assertEquals(status, expectedStatus);

    }

    @SuppressWarnings("unchecked")
	@Test
    public void getReceiptNotFound() throws ResourceNotFoundException, ApplicationException {

        int expectedStatus = 404;

        commonPreparation();

        when(voteService.getVoteReceipt(tenantId, electionEventId, votingCardId))
            .thenThrow(ResourceNotFoundException.class);

        int status = executeRequest();

        Assert.assertEquals(status, expectedStatus);

    }

    @SuppressWarnings("unchecked")
	@Test
    public void getReceiptApplicationException() throws ResourceNotFoundException, ApplicationException {

        int expectedStatus = 422;

        commonPreparation();

        when(voteService.getVoteReceipt(tenantId, electionEventId, votingCardId)).thenThrow(ApplicationException.class);

        int status = executeRequest();

        Assert.assertEquals(status, expectedStatus);

    }

    private int executeRequest() {
        return target(PATH).resolveTemplate("tenantId", tenantId).resolveTemplate("electionEventId", electionEventId)
            .resolveTemplate("votingCardId", votingCardId).request().get().getStatus();
    }

    private void commonPreparation() {
        when(servletRequest.getHeader("X-Request-ID")).thenReturn("request");
        when(servletRequest.getRemoteAddr()).thenReturn("");
        when(servletRequest.getLocalAddr()).thenReturn("");
    }

    @Override
    protected Application configure() {

        MockitoAnnotations.initMocks(this);

        AbstractBinder binder = new AbstractBinder() {
            @Override
            protected void configure() {
                bind(trackIdInstance).to(TrackIdInstance.class);
                bind(logger).to(Logger.class);
                bind(servletRequest).to(HttpServletRequest.class);
                bind(httpRequestService).to(HttpRequestService.class);
                bind(voteService).to(VoteService.class);
                bind(transactionInfoProvider).to(TransactionInfoProvider.class);
            }
        };
        sut = new ReceiptResource();
        forceSet(TestProperties.CONTAINER_PORT, "0");
        return new ResourceConfig().register(sut).register(binder)
                .register(new ResourceNotFoundExceptionHandler())
                .register(new ApplicationExceptionHandler());
    }
}