/*
 * Copyright (c) eHealth
 */
package be.ehealth.businessconnector.therlink.service.impl;

import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import be.ehealth.business.common.domain.Patient;
import be.ehealth.business.kmehrcommons.HcPartyUtil;
import be.ehealth.businessconnector.therlink.builders.CommonObjectBuilder;
import be.ehealth.businessconnector.therlink.builders.ProofBuilder;
import be.ehealth.businessconnector.therlink.builders.RequestObjectBuilder;
import be.ehealth.businessconnector.therlink.builders.RequestObjectBuilderFactory;
import be.ehealth.businessconnector.therlink.domain.Author;
import be.ehealth.businessconnector.therlink.domain.HcParty;
import be.ehealth.businessconnector.therlink.domain.Proof;
import be.ehealth.businessconnector.therlink.domain.TherapeuticLink;
import be.ehealth.businessconnector.therlink.domain.requests.GetTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.requests.PutTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.requests.RevokeTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.responses.GeneralResponse;
import be.ehealth.businessconnector.therlink.domain.responses.GetTherapeuticLinkResponse;
import be.ehealth.businessconnector.therlink.domain.responses.PutTherapeuticLinkResponse;
import be.ehealth.businessconnector.therlink.domain.responses.RevokeTherapeuticLinkResponse;
import be.ehealth.businessconnector.therlink.domain.responses.TherapeuticLinkResponseError;
import be.ehealth.businessconnector.therlink.exception.TherLinkBusinessConnectorException;
import be.ehealth.businessconnector.therlink.mappers.MapperFactory;
import be.ehealth.businessconnector.therlink.mappers.RequestObjectMapper;
import be.ehealth.businessconnector.therlink.mappers.ResponseObjectMapper;
import be.ehealth.businessconnector.therlink.service.ServiceFactory;
import be.ehealth.businessconnector.therlink.service.TherLinkService;
import be.ehealth.businessconnector.therlink.util.ConfigReader;
import be.ehealth.businessconnector.therlink.util.TherapeuticLinkTypeValues;
import be.ehealth.businessconnector.therlink.util.TherlinkTestUtils;
import be.ehealth.technicalconnector.config.ConfigFactory;
import be.ehealth.technicalconnector.config.ConfigValidator;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.service.sts.security.SAMLToken;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.session.impl.SessionManagerImpl;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;

/**
 * Unit test for {@link TherLinkService}
 * 
 * @author EHP
 * 
 */
public class TherLinkServiceBasicIntegrationTest extends AbstractTherlinkIsolationIntegrationTest {

    /**
     * @throws TherLinkBusinessConnectorException
     * @throws TechnicalConnectorException
     * @throws InstantiationException
     */
    public TherLinkServiceBasicIntegrationTest() throws TherLinkBusinessConnectorException, TechnicalConnectorException, InstantiationException {
        super();
    }

    private static final String MAIN_KMEHR_QUALITY = "main.kmehr.quality";

    private static String linkType;

    private static final Logger LOG = LoggerFactory.getLogger(TherLinkServiceBasicIntegrationTest.class);

    private static HcParty concernedHealthCareProfessional;

    @BeforeClass
    public static void init() throws Exception {
        Session.getInstance().unloadSession();
        SessionInitializer.init("/be.ehealth.businessconnector.therlink.test.properties", true);
        // initSessionAndCleanTherlinks();

        ConfigValidator configValidator = ConfigFactory.getConfigValidator();
        linkType = TherapeuticLinkTypeValues.valueOf(configValidator.getProperty(MAIN_KMEHR_QUALITY).toUpperCase()).getTherlinkType();
        concernedHealthCareProfessional = ConfigReader.getCareProvider();
    }

    @Before
    public void removeExistingLinks() throws Exception {
        TherlinkTestUtils.revokeNonReferrals(TherlinkTestUtils.getOfflinePatient());
    }

    @Test
    public void putTherapeuticLink() throws Exception {
        TherLinkService therLinkService = ServiceFactory.getTherLinkService();
        SAMLToken samlToken = Session.getInstance().getSession().getSAMLToken();

        Proof proof = RequestObjectBuilderFactory.getProofBuilder().createProofForEidReading();
        Patient patient = TherlinkTestUtils.fillTherlinkPatientWithOfflinePatientDataForProof(proof);

        PutTherapeuticLinkRequest request = RequestObjectBuilderFactory.getRequestObjectBuilder().createPutTherapeuticLinkRequest(null, patient, concernedHealthCareProfessional, linkType, null, proof);

        be.fgov.ehealth.hubservices.core.v2.PutTherapeuticLinkRequest mapPutTherapeuticLinkRequest = MapperFactory.getRequestObjectMapper().mapPutTherapeuticLinkRequest(request);

        be.fgov.ehealth.hubservices.core.v2.PutTherapeuticLinkResponse putTherapeuticLink = therLinkService.putTherapeuticLink(samlToken, mapPutTherapeuticLinkRequest);
        PutTherapeuticLinkResponse response = MapperFactory.getResponseObjectMapper().mapJaxbToPutTherapeuticLinkResponse(putTherapeuticLink);

        LOG.info(response.toString());
        logResponseAndCheckIfNoErrors(response);
    }

    @Test
    public void putTherapeuticLinkWithIsi() throws Exception {
        Patient patient = new Patient.Builder().withInss("08013126873").withFirstName("dummyname").withLastName("dummyName").withIsiPlus("9950014769").build();
        Proof isiProof = proofBuilder.createProofForIsiReading();
        TherlinkTestUtils.revokeNonReferrals(patient, isiProof);
        TherLinkService therLinkService = ServiceFactory.getTherLinkService();
        SAMLToken samlToken = Session.getInstance().getSession().getSAMLToken();

        PutTherapeuticLinkRequest request = requestObjectBuilder.createPutTherapeuticLinkRequest(null, patient, concernedHealthCareProfessional, linkType, null, isiProof);

        be.fgov.ehealth.hubservices.core.v2.PutTherapeuticLinkRequest mapPutTherapeuticLinkRequest = requestObjectMapper.mapPutTherapeuticLinkRequest(request);

        be.fgov.ehealth.hubservices.core.v2.PutTherapeuticLinkResponse putTherapeuticLink = therLinkService.putTherapeuticLink(samlToken, mapPutTherapeuticLinkRequest);
        PutTherapeuticLinkResponse response = responseObjectMapper.mapJaxbToPutTherapeuticLinkResponse(putTherapeuticLink);

        LOG.info(response.toString());
        logResponseAndCheckIfNoErrors(response);
    }

    /**
     * @param response
     */
    private void logResponseAndCheckIfNoErrors(PutTherapeuticLinkResponse response) {
        LOG.info(response.toString());
        Assert.assertNotNull(response);
        Assert.assertNotNull(response.getAcknowledge());
        Assert.assertNotNull(response.getAcknowledge().getListOfErrors());
        checkErrors(response);
    }

    @Test
    public void getTherapeuticLink() throws Exception {
        // create builders
        CommonObjectBuilder commonBuilder = RequestObjectBuilderFactory.getCommonBuilder();
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();
        ProofBuilder proofBuilder = RequestObjectBuilderFactory.getProofBuilder();
        RequestObjectMapper requestObjectMapper = MapperFactory.getRequestObjectMapper();
        SAMLToken samlToken = Session.getInstance().getSession().getSAMLToken();
        ResponseObjectMapper responseObjectMapper = MapperFactory.getResponseObjectMapper();
        TherLinkService service = ServiceFactory.getTherLinkService();

        // retrieve all info to create therapeutic link
        String kmehrId = commonBuilder.createKmehrID();
        Author author = commonBuilder.createAuthor(requestObjectBuilder.getAuthorHcParties());

        Proof proof = proofBuilder.createProofForEidReading();
        Patient patientInfo = TherlinkTestUtils.fillTherlinkPatientWithOfflinePatientDataForProof(proof);
        HcParty careProviderHcParty = ConfigReader.getCareProvider();
        TherapeuticLink therapeuticLink = commonBuilder.createTherapeuticLink(new DateTime(), new DateTime().plusMonths(6), patientInfo, HcPartyUtil.getAuthorKmehrQuality(), null, null, careProviderHcParty);

        int maxRows = requestObjectBuilder.getMaxRows();


        GetTherapeuticLinkRequest request = new GetTherapeuticLinkRequest(new DateTime(), kmehrId, author, therapeuticLink, maxRows, proof);

        be.fgov.ehealth.hubservices.core.v2.GetTherapeuticLinkRequest mappedRequest = requestObjectMapper.mapGetTherapeuticLinkRequest(request);

        be.fgov.ehealth.hubservices.core.v2.GetTherapeuticLinkResponse getTherapeuticLinkResponse = service.getTherapeuticLink(samlToken, mappedRequest);
        GetTherapeuticLinkResponse response = responseObjectMapper.mapJaxbToGetTherapeuticLinkResponse(getTherapeuticLinkResponse);

        LOG.info(response.toString());
        Assert.assertNotNull(response);
        Assert.assertNotNull(response.getAcknowledge());
        Assert.assertNotNull(response.getAcknowledge().getListOfErrors());
        checkErrors(response);
    }

    /**
     * @param response
     */
    private void checkErrors(GeneralResponse response) {
        if (response.getAcknowledge().getListOfErrors().size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (TherapeuticLinkResponseError error : response.getAcknowledge().getListOfErrors()) {
                String errorDescription = error.getErrorDescription();
                String errorCode = error.getErrorCode();
                sb.append(errorCode).append(" : ").append(errorDescription).append(" ");
            }
            Assert.fail(sb.toString());
        }
    }

    @Test
    public void revokeTherapeuticLink() throws Exception {
        Proof proof = proofBuilder.createProofForEidReading();
        Patient patient = TherlinkTestUtils.fillTherlinkPatientWithOfflinePatientDataForProof(proof);
        HcParty concernedHealthCareProfessionel = ConfigReader.getCareProvider();
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();
        ResponseObjectMapper responseObjectMapper = MapperFactory.getResponseObjectMapper();
        RequestObjectMapper requestObjectMapper = MapperFactory.getRequestObjectMapper();

        TherLinkService service = ServiceFactory.getTherLinkService();
        PutTherapeuticLinkRequest putRequest = requestObjectBuilder.createPutTherapeuticLinkRequest(patient, concernedHealthCareProfessionel, linkType, proof);
        service.putTherapeuticLink(SessionManagerImpl.getInstance().getSession().getSAMLToken(), MapperFactory.getRequestObjectMapper().mapPutTherapeuticLinkRequest(putRequest));

        RevokeTherapeuticLinkRequest request = requestObjectBuilder.createRevokeTherapeuticLinkRequest(new DateTime(), null, patient, concernedHealthCareProfessionel, linkType, null, proof);

        SAMLToken samlToken = Session.getInstance().getSession().getSAMLToken();
        be.fgov.ehealth.hubservices.core.v2.RevokeTherapeuticLinkRequest mapRevokeTherapeuticLinkRequest = requestObjectMapper.mapRevokeTherapeuticLinkRequest(request);
        be.fgov.ehealth.hubservices.core.v2.RevokeTherapeuticLinkResponse revokeTherapeuticLink = service.revokeTherapeuticLink(samlToken, mapRevokeTherapeuticLinkRequest);
        RevokeTherapeuticLinkResponse response = responseObjectMapper.mapJaxbToRevokeTherapeuticLinkResponse(revokeTherapeuticLink);


        LOG.info(response.toString());
        Assert.assertNotNull(response);
        Assert.assertNotNull(response.getAcknowledge());
        Assert.assertNotNull(response.getAcknowledge().getListOfErrors());
        checkErrors(response);
    }

}
