/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.technicalconnector.bootstrap.bcp;

import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.ws.ServiceFactory;
import be.ehealth.technicalconnector.ws.domain.GenericRequest;
import be.fgov.ehealth.technicalconnector.tests.junit.rule.EndpointUpdateRule;
import be.fgov.ehealth.technicalconnector.tests.server.EchoResponse;
import be.fgov.ehealth.technicalconnector.tests.server.HttpServerStub;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;
import org.junit.*;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import javax.xml.ws.soap.SOAPFaultException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author EH053
 */

@RunWith(Parameterized.class)
public class GenericRequestTest {

    private static final String DUMMY_PAYLOAD = "<test>hello</test>";

    private static final String URL_BCP_ALTERNATIVE = "http://localhost:6666/error/403";

    private static final String URL_BCP_ERROR = "http://localhost:7777/error/404";

    private static final String URL_BCP_NO_ALTERNATIVE = "http://localhost:8888/error/403";

    private static final String URL_BCP_LOOP = "http://localhost:9999/error/403";


    @Parameterized.Parameters(name = "{0}")
    public static List<Object[]> input() {
        return Arrays.asList(new Object[][]{{"serviceList V1", "/samples/servicelist/local/servicelist-local"}, {"serviceList V2", "/samples/servicelist/local/servicelistv2-local"}});
    }

    public GenericRequestTest(String name, String endpointLocation) {
        rule.setLocation(endpointLocation);
    }


    @Rule
    public ExpectedException expect = ExpectedException.none();

    private static List<HttpServerStub> servers = new ArrayList<HttpServerStub>();

    @BeforeClass
    public static void before() throws Exception {
        LoggingUtils.bootstrap();
        HttpServerStub server9999 = new HttpServerStub(9999);
        server9999.add("/error/403", (String) null);
        server9999.add("/timeout/30", (String) null);
        servers.add(server9999);

        HttpServerStub server6666 = new HttpServerStub(6666);
        server6666.add("/error/403", (String) null);
        server6666.add("/echo", (String) null);
        servers.add(server6666);

        HttpServerStub server7777 = new HttpServerStub(7777);
        server7777.add("/error/403", (String) null);
        server7777.add("/timeout/60", (String) null);
        String body = "<soapenv:Envelope  xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "    <soapenv:Body>\n" +
                "        <soapenv:Fault>\n" +
                "            <faultcode>soapenv:Client</faultcode>\n" +
                "            <faultstring>SOA-03006: XSD compliance failure: cvc-complex-type.2.4.a: Invalid content was found starting with element is expected.</faultstring>\n" +
                "            <detail>\n" +
                "                <urn:SystemError Id=\"Id-e32e6e5d7c24d5fa8f052607\" xmlns:urn=\"urn:be:fgov:ehealth:errors:soa:v1\">\n" +
                "                    <Origin>Consumer</Origin>\n" +
                "                    <Code>SOA-03006</Code>\n" +
                "                    <Message xml:lang=\"en\">XSD compliance failure: cvc-complex-type.2.4.a: Invalid content was found starting with element  is expected.</Message>\n" +
                "                    <urn:Environment>Integration</urn:Environment>\n" +
                "                </urn:SystemError>\n" +
                "            </detail>\n" +
                "        </soapenv:Fault>\n" +
                "    </soapenv:Body>\n" +
                "</soapenv:Envelope>";
        server7777.add("/soap/error/business", body);
        server7777.add("/soap/error/business", body);
        servers.add(server7777);

        HttpServerStub server8888 = new HttpServerStub(8888);
        server8888.add("/error/403", (String) null);
        servers.add(server8888);
    }

    @AfterClass
    public static void after() {
        for (HttpServerStub server : servers) {
            server.shutdown();
        }

    }

    @Rule
    public EndpointUpdateRule rule = new EndpointUpdateRule();

    @Test
    public void invokeWithRetrySuccess() throws Exception {
        GenericRequest req = new GenericRequest();
        req.setPayload(DUMMY_PAYLOAD);
        req.setEndpoint(URL_BCP_ALTERNATIVE);
        EchoResponse echoResponse = ServiceFactory.getGenericWsSender()
                .send(req)
                .asObject(EchoResponse.class);

        Assert.assertTrue(echoResponse.getInbound().getFiles().get("body").contains(DUMMY_PAYLOAD));
        Assert.assertTrue(EndpointDistributor.getInstance().mustPoll());
    }

    @Test
    public void invokeWithRetrySOAPFault() throws Exception {
        expect.expect(SOAPFaultException.class);
        expect.expectMessage("SOA-03006");

        GenericRequest req = new GenericRequest();
        req.setPayload(DUMMY_PAYLOAD);
        req.setEndpoint(URL_BCP_ERROR);
        ServiceFactory.getGenericWsSender().send(req).getSOAPException();

        Assert.assertTrue(EndpointDistributor.getInstance().mustPoll());
    }

    @Test
    public void invokeLoop() throws Exception {
        expect.expect(TechnicalConnectorException.class);
        expect.expectMessage("403");
        GenericRequest req = new GenericRequest();
        req.setPayload(DUMMY_PAYLOAD);
        req.setEndpoint(URL_BCP_LOOP);
        ServiceFactory.getGenericWsSender()
                .send(req)
                .getSOAPException();
        Assert.assertFalse(EndpointDistributor.getInstance()
                .mustPoll());
    }

    @Test
    public void invokeNoAlternative() throws Exception {
        expect.expect(TechnicalConnectorException.class);
        expect.expectMessage("403");
        GenericRequest req = new GenericRequest();
        req.setPayload(DUMMY_PAYLOAD);
        req.setEndpoint(URL_BCP_NO_ALTERNATIVE);
        ServiceFactory.getGenericWsSender()
                .send(req);
        Assert.assertFalse(EndpointDistributor.getInstance()
                .mustPoll());
    }

}

