package be.ehealth.businessconnector.ehbox.v3.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import be.ehealth.businessconnector.ehbox.api.domain.Addressee;
import be.ehealth.businessconnector.ehbox.api.domain.NewsMessage;
import be.ehealth.businessconnector.ehbox.api.utils.QualityType;
import be.ehealth.businessconnector.ehbox.v3.EhboxTestDataBuilder;
import be.ehealth.businessconnector.ehbox.v3.EhboxTestUtilities;
import be.ehealth.businessconnector.ehbox.v3.builders.BuilderFactory;
import be.ehealth.businessconnector.ehbox.v3.builders.SendMessageBuilder;
import be.ehealth.businessconnector.ehbox.v3.session.EhealthBoxServiceV3;
import be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.IdentifierType;
import be.fgov.ehealth.commons.protocol.v1.ResponseType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetBoxInfoRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetBoxInfoResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetHistoryRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetHistoryResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetMessageListResponseType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.Message;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.MoveMessageRequest;
import be.fgov.ehealth.ehbox.publication.protocol.v3.SendMessageRequest;
import be.fgov.ehealth.ehbox.publication.protocol.v3.SendMessageResponse;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;
import be.fgov.ehealth.technicalconnector.tests.utils.TestPropertiesLoader;

/**
 * eHealthBox Service Integration Tests This test shows the use of the eHealthBox Service through the use of the Business Connector.
 * 
 * The tests below use the Session Management Service to manage the session and SAML/STS token. The eHealthBox of the test user specified in
 * the business connector property file is used, these tests expect that this is set to a valid INSS of a citizen.
 * 
 * @author EHP
 * 
 */
public class ConsultationServiceImplIntegrationTest {

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

    private static boolean isDoctorTest;

    /**
     * Id of the response
     */
    private static String messageId;

    @BeforeClass
    public static void initializeProperties() throws Exception {
        Properties props = TestPropertiesLoader.getProperties("/be.ehealth.businessconnector.ehboxv3.test.properties");
        isDoctorTest = EhboxTestUtilities.isDoctorTest(props);
        Session.getInstance().unloadSession();
        SessionInitializer.init(props, true);
    }


    @AfterClass
    public static void unloadSession() throws Exception {
        Session.getInstance().unloadSession();
    }

    /**
     * Test the getBoxInfo operation from the eHealthBox Service through the use of the Business Connector. The getBoxInfo retrieves general
     * info about an eHealthBox
     * 
     * The following main steps are done: - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    public void testGetBoxInfo() throws Exception {
        /*
         * Invoke the business connector framework's eHealthBox's getBoxInfo operation
         */
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetBoxInfoRequest getBoxInfoRequest = new GetBoxInfoRequest();
        GetBoxInfoResponse response = service.getBoxInfo(getBoxInfoRequest);

        /*
         * Verify the response
         */
        // check if there are no errors
        Assert.assertEquals("100", response.getStatus().getCode());
        // check if there is any content
        Assert.assertNotNull(response.getBoxId());
    }

    /**
     * Initialize messageId if not already done.
     * 
     * @throws Exception
     */
    @Before
    public void init() throws Exception {
        if (messageId != null) {
            LOG.warn("News already initialized.");
        } else {
            // Creating destination List
            List<Addressee> addresseeList = new ArrayList<Addressee>();
            Addressee addressee = new Addressee(IdentifierType.SSIN);
            addressee.setId(EhboxTestDataBuilder.getInssUser1());
            addressee.setQuality(QualityType.DOCTOR_SSIN);
            addresseeList.add(addressee);

            // Creating the news
            SendMessageBuilder builder = BuilderFactory.getSendMessageBuilder();

            NewsMessage<Message> news = new NewsMessage<Message>();
            news.getDocument().setTitle("News " + new Date());
            news.getDocument().setContent("eureka".getBytes());
            news.getDocument().setFilename("test.txt");
            news.setDestinations(addresseeList);
            news.setImportant(true);
            news.setEncrypted(false);

            SendMessageRequest request = builder.buildMessage(news);

            // Invoke the business connector framework's eHealthBox's sendMessage operation
            EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
            SendMessageResponse response = service.sendMessage(request);


            // Verify the response
            // check if there are no errors
            Assert.assertEquals("100", response.getStatus().getCode());
            // check if a messageId has been returned
            Assert.assertNotNull(response.getId());

            LOG.debug("Message Sent: " + response.getId());

            // save for use in next tests
            messageId = response.getId();
        }
    }

    /**
     * Test the getMessageList operation from the eHealthBox Service through the use of the Business Connector. This test retrieves the
     * messageId's of the message's in a given folder, correct values for the folder are: INBOX | SENT | BIN
     * 
     * The following main steps are done: - Create the parameters of the new message - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    public void testGetMessageList() throws Exception {
        /*
         * Create the parameters of the new message
         */
        // set the folder (INBOX | SENTBOX | BININBOX | BINSENTBOX)
        String source = "INBOX";

        GetMessageListResponseType response = EhboxTestUtilities.retrieveMessageFromSourceAndCheckStatus(source);
        // print out the messageId's for the given folder
        List<Message> list = response.getMessages();
        LOG.info("Messages in " + source);
        for (Message message : list) {
            // JAXB.marshal(message, System.out);
            try {
                be.ehealth.businessconnector.ehbox.api.domain.Message<Message> msg = BuilderFactory.getConsultationMessageBuilder().buildMessage(message);
                LOG.info(msg.toString());
            } catch (Exception e) {
                LOG.info("\t exception " + e.getMessage() + " for message with id " + message.getMessageId());
                Assert.fail("exception occured : " + e.getMessage());
            }
        }
    }

    @Test
    public void testShowAllErrorMessagesForInbox() throws Exception {
        String source = "INBOX";

        EhboxTestUtilities.showMessagesFromSource(source);
    }

    /**
     * Test the getFullMessage operation from the eHealthBox Service through the use of the Business Connector. This test retrieves a full
     * message based on a given messageId's. Usually the messageId is retrieved first from the getMessageList operation.
     * 
     * The following main steps are done: - Create the parameters of the new message - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    // @Ignore
    public void testGetFullMessage() throws Exception {
        Assume.assumeTrue(isDoctorTest);
        String source = "INBOX";
        GetMessageListResponseType messagesListResponse = EhboxTestUtilities.retrieveMessageFromSourceAndCheckStatus(source);
        if (messagesListResponse.getMessages() == null || messagesListResponse.getMessages().isEmpty()) {
            Assert.fail("no messages to retrieve : cannot execute getFullMessage test");
        }
        String fullMessageId = messagesListResponse.getMessages().get(0).getMessageId();
        GetFullMessageResponse response = EhboxTestUtilities.getFullMessage(source, fullMessageId);

        /*
         * Verify the response
         */

        // check if the message has been returned
        Assert.assertNotNull(response.getMessage().getPublicationId());
        be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> msg = BuilderFactory.getConsultationMessageBuilder().buildFullMessage(response);
        Assert.assertNotNull(msg);
        LOG.debug(msg.toString());

        // }

    }

    /**
     * Test the getHistory operation from the eHealthBox Service through the use of the Business Connector. This test retrieves the history
     * based on a given messageId. the list that is returned is a list of Strings containing messageId's.
     * 
     * The following main steps are done: - Create the parameters of the new message - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    public void testGetHistory() throws Exception {
        /*
         * Create the parameters of the new message
         */
        GetHistoryRequest request = new GetHistoryRequest();
        // set the messageId, use the messageId of the message that has been sent in testSendMessage
        request.setMessageId(messageId);
        request.setSource("INBOX");

        /*
         * Invoke the business connector framework's eHealthBox's getFullMessage operation
         */
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetHistoryResponse response = service.getMessageHistory(request);

        /*
         * Verify the response
         */
        // check if there are no errors
        Assert.assertEquals("100", response.getStatus().getCode());
        // check if the message has been returned
        Assert.assertNotNull(response.getMessageIds());
    }

    /**
     * Test the moveToInbox operation from the eHealthBox Service through the use of the Business Connector. This moves a message from the
     * BIN folder to the INBOX folder based on a given messageId.
     * 
     * The following main steps are done: - Create the parameters of the new message - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    public void testMoveToInbox() throws Exception {
        /*
         * Create the parameters of the new message
         */
        MoveMessageRequest request = new MoveMessageRequest();
        // set the messageId, use the messageId of the message that has been sent in testSendMessage
        request.getMessageIds().add(messageId);
        request.setSource("SENTBOX");
        request.setDestination("BINSENTBOX");

        /*
         * Invoke the business connector framework's eHealthBox's getFullMessage operation
         */

        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        ResponseType response = service.moveMessage(request);


        /*
         * Verify the response
         */
        // check if there are no errors
        Assert.assertEquals("100", response.getStatus().getCode());
    }


}
