package cz.moneta.test.system.wso2;

import com.fasterxml.jackson.annotation.JsonProperty;
import cz.moneta.test.dsl.Harness;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.annotations.TestScenario;
import cz.moneta.test.harness.support.rest.RawRestRequest;
import cz.moneta.test.harness.support.util.Template;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

import static cz.moneta.test.harness.annotations.Environment.PPE;
import static cz.moneta.test.harness.annotations.Environment.TST1;

@TestScenario(name = "Authenticates and calls a dummy request")
public class DummyRequestTest {

    private String token;
    private String uniPtKey;

    @BeforeAll
    public void setup(Harness harness) {
        token = harness.tasks().wso2().authorization().getToken("DigitalchannelsSB_CBL");
        uniPtKey = harness.getConfig("system.wso2.dummyrequesttest.uniptkey");
    }

    @Disabled
    @TestCase(name = "generates an authentication token")
    public void generateToken(Harness harness) {
        RawRestRequest.Response response = harness.withWso2()
                .prepareRequest()
                .withPath("token")
                .withHeader("Authorization", "Basic " +
                        "ZXR4bWZhS3phWTFEZlQ1aHdtZmhNY3VXSFdZYTpnVXd6ZlltTVhBUHZCcVBod2RlSEJYbjNIeHdh")
                .withPayload("grant_type=client_credentials")
                .post();

        Assertions.assertNotNull(response);
    }

    @TestCase(name = "calls a dummy request", environments = {TST1, PPE})
    public void callDummyRequest(Harness harness) {
        harness.withWso2()
                .prepareRequest()
                .withPath("/t/data.cluster/ODS/GET_ACC_DATA/001")
                .withHeader("activityId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("requestId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("Authorization", "Bearer " + token)
                .withHeader("Content-Type", "application/json")
                .withHeader("cache-control", "no-cache,no-cache")
                .withHeader("USERID_L2", "GEBTTOT")
                .withPayload("{" +
                        "  \"BUSINESS\": \"GEM\"," +
                        "  \"PURPOSE\": \"1\"," +
                        "  \"RS_1\": [" +
                        "    {" +
                        "       \"UNI_PT_KEY_IN\": \"" + uniPtKey + "\"" +
                        "    }" +
                        "  ]" +
                        "}")
                .post()
                .andAssertFieldValue("RS_4[0].DUE_INSUR_BAL", "0")
                .andAssertFieldValue("RS_4[1].ACC_SRC_SYS", "ICB01");
    }

    @TestCase(name = "calls a dummy request from file", environments = TST1)
    public void callDummyRequestFromFile(Harness harness) {
        harness.withWso2()
                .prepareRequest()
                .withPath("/t/data.cluster/ODS/GET_ACC_DATA/001")
                .withHeader("activityId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("requestId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("Authorization", "Bearer " + token)
                .withHeader("Content-Type", "application/json")
                .withHeader("cache-control", "no-cache,no-cache")
                .withHeader("USERID_L2", "GEBTTOT")
                .withPayloadFromFile("system/wso2/dummy_request_from_file_tst1.json")
                .post()
                .andAssertFieldValue("RS_4[0].DUE_INSUR_BAL", "0")
                .andAssertFieldValue("RS_4[1].ACC_SRC_SYS", "ICB01");
    }

    @TestCase(name = "calls a dummy request from file")
    public void callDummyRequestFromTemplate(Harness harness) {
        harness.withWso2()
                .prepareRequest()
                .withPath("/t/data.cluster/ODS/GET_ACC_DATA/001")
                .withHeader("activityId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("requestId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("Authorization", "Bearer " + token)
                .withHeader("Content-Type", "application/json")
                .withHeader("cache-control", "no-cache,no-cache")
                .withHeader("USERID_L2", "GEBTTOT")
                .withPayloadFromTemplate(Template.fromFilepath("system/wso2/dummy_request_from_template.json")
                        .set("UNI_PT_KEY", uniPtKey))
                .post()
                .andAssertFieldValue("RS_4[0].DUE_INSUR_BAL", "0")
                .andAssertFieldValue("RS_4[1].ACC_SRC_SYS", "ICB01");
    }

    @TestCase(name = "calls a dummy request from file")
    public void callDummyRequestAndJsonUnit(Harness harness) {
        harness.tasks().wso2().restRequest()
                .prepareRequestFromCbl("/t/data.cluster/ODS/GET_ACC_DATA/001",
                        Template.fromFilepath("system/wso2/dummy_request_from_template.json")
                                .set("UNI_PT_KEY", uniPtKey).render())
                .post()
                .andAssertStatus(200)
                .andAssertWithAssertJ().inPath("$.RS_4[?(@.ACC_SRC_SYS=='ICB03')]").isNotNull();
    }

    @Disabled("This API doesn't exist, this is just an example")
    @TestCase(name = "calls a dynamically created dummy request")
    public void callDynamicDummyRequest(Harness harness) {
        harness.withWso2()
                .prepareRequest()
                .withPath("t/training.gov/PHR_mapping_numbers/001")
                .withHeader("activityId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("requestId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("Authorization", "Bearer 6e017015-a2be-3777-9482-8985ca86ba3d")
                .withHeader("Content-Type", "application/json")
                .withHeader("cache-control", "no-cache,no-cache")
                .withHeader("USERID_L2", "GEBTTOT")
                .withPayload("{\"SPECIAL_CODE\": \"100\"}")
                .addField("", "RS_persons", Collections.emptyList())
                .appendToArray("RS_persons", new Dummy("abcd", "Adam", "Jihlava"))
                .appendToArray("RS_persons", new Dummy("aaaaaa", "David", "Plzeň"))
                .post()
                .andAssertFieldValue("RS_persons[0].my_string", "abcd")
                .andAssertFieldValue("RS_persons[1].my_string", "aaaaaa");

    }

    @Disabled("This API doesn't exist, this is just an example")
    @TestCase(name = "calls a dummy request created from pojo")
    public void callPojoDummyRequest(Harness harness) {
        DummyRequest request = DummyRequest.builder()
                .specialCode("100")
                .rsPersons(Arrays.asList(
                        new Dummy("abcd", "Adam", "Jihlava"),
                        new Dummy("aaaaaa", "David", "Plzeň")))
                .build();

        harness.withWso2()
                .prepareRequest()
                .withPath("t/training.gov/PHR_mapping_numbers/001")
                .withHeader("activityId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("requestId", harness.tasks().wso2().restRequest().getRandomId())
                .withHeader("Authorization", "Bearer 6e017015-a2be-3777-9482-8985ca86ba3d")
                .withHeader("Content-Type", "application/json")
                .withHeader("cache-control", "no-cache,no-cache")
                .withHeader("USERID_L2", "GEBTTOT")
                .withPojoPayload(request)
                .post()
                .andAssertFieldValue("RS_persons[0].my_string", "abcd")
                .andAssertFieldValue("RS_persons[1].my_string", "aaaaaa");

    }

    @Data
    @Builder
    @AllArgsConstructor
    private static class DummyRequest {
        @JsonProperty("SPECIAL_CODE")
        private String specialCode;
        @JsonProperty("RS_persons")
        private Collection<Dummy> rsPersons;
    }

    @Data
    @AllArgsConstructor
    private static class Dummy {
        @JsonProperty("my_string")
        private String myString;
        private String name;
        private String city;
    }

}
