/*
 * Copyright (c) eHealth
 */
package be.ehealth.technicalconnector.service.idsupport;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.Arrays;

import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import be.ehealth.technicalconnector.exception.SoaErrorException;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.service.ServiceFactory;
import be.fgov.ehealth.commons.core.v2.Id;
import be.fgov.ehealth.idsupport.core.v2.IdentificationData;
import be.fgov.ehealth.idsupport.protocol.v2.VerifyIdRequest;
import be.fgov.ehealth.idsupport.protocol.v2.VerifyIdResponse;
import be.fgov.ehealth.technicalconnector.tests.junit.rule.SessionRule;

/**
 * @author EHP
 */
public class IdSupportServiceIntegrationTest {

    @ClassRule
    public static SessionRule rule = SessionRule.withActiveSession()
                                                .build();

    private static final String REQUEST_ID = "ID_1990000332.20131218093047194";

    private static final String LEGAL_CONTEXT = "patient insurance validation";

    private static final String URN_SSIN = "urn:be:fgov:person:ssin";

    private static final String URN_CARD_NUMBER = "urn:be:fgov:person:cardsupport:cardnumber";

    private static final String SUCCESS = "urn:be:fgov:ehealth:2.0:status:Success";

    private static final String URN_BARCODED = "urn:be:fgov:person:cardsupport:barcoded";

    private static String ssin;

    private static String cardNumber;

    private static String barcode;

    private static IdSupportService service;

    @BeforeClass
    public static void initIdSupport() throws Exception {
        service = ServiceFactory.getIdSupportService();
    }

    @Before
    public void before() {
        ssin = rule.getSessionProperty("test.idsupport.ssin");
        assertNotNull(ssin);

        cardNumber = rule.getSessionProperty("test.idsupport.cardnumber");
        assertNotNull(cardNumber);

        barcode = rule.getSessionProperty("test.idsupport.barcode");
        assertNotNull(barcode);
    }

    @Test
    public void happyPath() throws TechnicalConnectorException {
        VerifyIdResponse response = service.verifyId(getRequestWithSsinAndCardNumber(ssin, cardNumber));

        assertEquals(SUCCESS, response.getStatus()
                                      .getStatusCode()
                                      .getValue());
    }

    @Test
    public void happyPathWithSsinAndCardNumber() throws TechnicalConnectorException {
        VerifyIdResponse response = service.verifyId(LEGAL_CONTEXT, id(URN_SSIN, ssin), id(URN_CARD_NUMBER, cardNumber));

        assertEquals(SUCCESS, response.getStatus()
                                      .getStatusCode()
                                      .getValue());
    }

    @Test
    public void happyPathWithBarcode() throws TechnicalConnectorException {
        VerifyIdResponse response = service.verifyId(LEGAL_CONTEXT, id(URN_BARCODED, barcode));

        assertEquals(SUCCESS, response.getStatus()
                                      .getStatusCode()
                                      .getValue());
    }

    @Test(expected = SoaErrorException.class)
    public void verifyIdWithValidationFailure() throws TechnicalConnectorException {
        VerifyIdResponse response = service.verifyId(getRequestWithBarcode(""));

        assertEquals("urn:be:fgov:ehealth:2.0:status:Requester", response.getStatus()
                                                                         .getStatusCode()
                                                                         .getValue());
        assertEquals("urn:be:fgov:ehealth:2.0:status:InvalidInput", response.getStatus()
                                                                            .getStatusCode()
                                                                            .getStatusCode()
                                                                            .getValue());
    }


    // Private helpers
    private static VerifyIdRequest getRequestWithBarcode(String barcode) {
        VerifyIdRequest request = getBasicRequest(LEGAL_CONTEXT, REQUEST_ID);
        request.setIdentificationData(identificationData(id(URN_BARCODED, barcode)));

        return request;
    }

    private static VerifyIdRequest getRequestWithSsinAndCardNumber(String ssin, String cardNumber) {
        VerifyIdRequest request = getBasicRequest(LEGAL_CONTEXT, REQUEST_ID);
        request.setIdentificationData(identificationData(id(URN_SSIN, ssin), id(URN_CARD_NUMBER, cardNumber)));
        return request;
    }

    private static Id id(String type, String value) {
        Id id = new Id();
        id.setType(type);
        id.setValue(value);


        return id;
    }

    private static VerifyIdRequest getBasicRequest(String legalContext, String id) {
        VerifyIdRequest request = new VerifyIdRequest();

        request.setId(id);
        request.setLegalContext(legalContext);
        request.setIssueInstant(new DateTime());

        return request;
    }

    private static IdentificationData identificationData(Id... ids) {
        IdentificationData identificationData = new IdentificationData();
        identificationData.getIds()
                          .addAll(Arrays.asList(ids));

        return identificationData;
    }
}
