package cz.moneta.test.dsl.util.task.szrmocktasks;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.szrmock.SzrMockData;
import cz.moneta.test.dsl.szrmock.SzrMockPayload;
import cz.moneta.test.dsl.util.task.wso2.ClientTasks;
import cz.moneta.test.harness.exception.HarnessException;
import cz.moneta.test.harness.support.auth.AuthSupport;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.rest.RawRestRequest;

import java.util.Base64;
import java.util.stream.Stream;

/**
 * FOR LOCAL USE ONLY!!! DO NOT USE IN JENKINS!!!
 * To use this in Jenkins, it is necessary to create and configure a technical account for the SZR mock service.
 */
public class SzrMockTasks {

    private final Harness harness;
    private final SzrMockPayload payload = new SzrMockPayload();
    private static final String GET_PATH = "/api/v1/internal/szr/mock/get";
    private static final String POST_SAVE_PATH = "/api/v1/internal/szr/mock/save";
    private static final String CONTENT_TYPE_JSON = "application/json";

    public SzrMockTasks(Harness harness) {
        this.harness = harness;
    }

    private String generateSzrId() {
        String generatedSzrId = Stream.generate(this::getRandomSzrId)
                .limit(10)
                .filter(szrId -> !szrIdExists(szrId))
                .findFirst()
                .orElseThrow(() -> new HarnessException("Generated existing combination 10 times"));

        harness.log("Generated srzId is \"" + generatedSzrId + "\"");
        return generatedSzrId;
    }

    private String getRandomSzrId() {
        String uuid = java.util.UUID.randomUUID().toString();
        return uuid.substring(0, uuid.length() - 6);
    }

    public RawRestRequest.Request prepareRequest(String path) {
        Credentials cred = AuthSupport.getCredentials("szr-mock", harness);
        String token = "Basic " + Base64.getEncoder().encodeToString((cred.getUsername() + ":" + cred.getPassword()).getBytes());
        return harness.withSzrMock()
                .prepareRequest()
                .withPath(path)
                .withHeader("Authorization", token)
                .withHeader("Content-Type", CONTENT_TYPE_JSON);
    }

    private boolean szrIdExists(String szrId) {
        return !prepareRequest(GET_PATH)
                .withPayload("{}")
                .addField("source", "MOCK")
                .addField("szrId", szrId)
                .addField("pageNumber", 1)
                .post()
                .andAssertStatus(200)
                .extract("result")
                .asText()
                .isEmpty();
    }
    
    private RawRestRequest.Response save(String payload) {
        return this.prepareRequest(POST_SAVE_PATH)
                .withPayload(payload)
                .post()
                .andAssertStatus(201);
    }

    private void saveE278_5(SzrMockData data) {
        this.save(payload.getPayloadE278Slash5(data));
    }

    private void saveE171(SzrMockData data) {
        this.save(payload.getPayloadE171(data));
    }

    private void saveE173(SzrMockData data) {
        this.save(payload.getPayloadE173(data));
    }

    private void saveE188(SzrMockData data) {
        this.save(payload.getPayloadE188(data));
    }

    private void saveE189(SzrMockData data) {
        this.save(payload.getPayloadE189(data));
    }

    private void saveE45(SzrMockData data) {
        this.save(payload.getPayloadE45(data));
    }

    public void idAndPassE2E(SzrMockData data) {
        data.setSzrId(generateSzrId());
        saveE278_5(data);
        saveE171(data);
        saveE173(data);
        saveE188(data);
        saveE189(data);
        saveE45(data);
        new ClientTasks(harness).doClientEgovIdentityComplete(
                data.getClient(),
                data.getCif(),
                data.getLivingPlaceNumber(),
                AuthSupport.getCredentials("szr-mock", harness).getUsername(),
                "ICB0",
                "86006810",
                data.getBusCode());
    }
}
