package cz.moneta.test.dsl.util.task.wso2.rest;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.util.credentials.Keys;
import cz.moneta.test.harness.support.auth.AuthSupport;
import cz.moneta.test.harness.support.rest.RawRestRequest;

import java.util.UUID;

public class RequestTasks {

    private static final String UFO = "UFO";
    private static final String WPS = "WPS";
    private static final String ATM = "ATM";
    private static final String HUB = "HUB";
    private static final String CBL = "CBL";
    private static final String PAY = "PAY";
    private static final String EXEVIDO = "EXEVIDO";
    private static final String ILODS = "ILODS";

    private final Harness harness;
    private Long readTimeout;

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

    /**
     * Setup read timeout of REST call
     * Default is 10
     * @param readTimeout timeout in seconds
     */
    public RequestTasks withCustomReadTimeout(long readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    public RawRestRequest.Post prepareEmptyRequestFromUfo(String path) {
        return prepareEmptyRequest(path, UFO, UFO);
    }

    public RawRestRequest.Post prepareEmptyRequestFromWps(String path) {
        return prepareEmptyRequest(path, WPS, WPS);
    }

    public RawRestRequest.Post prepareEmptyRequestFromAtm(String path) {
        return prepareEmptyRequest(path, ATM, ATM);
    }

    public RawRestRequest.Post prepareEmptyRequestFromCbl(String path) {
        return prepareEmptyRequest(path, CBL, "DigitalchannelsSB_CBL");
    }

    public RawRestRequest.Post prepareEmptyRequestFromHub(String path) {
        return prepareEmptyRequest(path, HUB, HUB);
    }

    public RawRestRequest.Post prepareEmptyRequestFromNas(String path) {
        return prepareEmptyRequest(path, "NAS", "RISK_NAS");
    }

    public RawRestRequest.Post prepareEmptyRequestFromErn(String path) {
        return prepareEmptyRequest(path, "ERN", "RISKCOLLECTIONS_ERN");
    }

    public RawRestRequest.Post prepareEmptyRequestFromIcb(String path) {
        return prepareEmptyRequest(path, "ICB", "PAYMENTS_ICB");
    }

    public RawRestRequest.Post prepareEmptyRequestFromPay(String path) {
        return prepareEmptyRequest(path, PAY, "");
    }

    public RawRestRequest.Post prepareEmptyRequestFromGvp(String path) {
        return prepareEmptyRequest(path, "GVP", "GVP");
    }

    public RawRestRequest.Post prepareRequestFromCbl(String path, String payload) {
        String cblToken = harness.tasks().wso2().authorization().getToken("DigitalchannelsSB_CBL");
        return prepareRequest(path, cblToken, CBL, payload);
    }

    public RawRestRequest.Post prepareRequestFromRefinansoHyp(String path, String payload) {
        String token = harness.tasks().wso2().authorization().getToken("REFINANSO_HYP");
        return prepareRequest(path, token, "REFINANSO_HYP", payload);
    }

    public RawRestRequest.Request prepareRequestFromUfo(String path) {
        String token = harness.tasks().wso2().authorization().getToken(UFO);
        return prepareRequest(path, token, UFO);
    }

    public RawRestRequest.Request prepareRequestFromIlods(String path) {
        String token = harness.tasks().wso2().authorization().getToken(ILODS);
        return prepareRequest(path, token, ILODS);
    }

    public RawRestRequest.Request prepareRequestFromHub(String path) {
        String token = harness.tasks().wso2().authorization().getToken(HUB);
        return prepareRequest(path, token, HUB);
    }

    public RawRestRequest.Request prepareRequestFromExevido(String path) {
        String token = harness.tasks().wso2().authorization().getToken("EXEVIDO_EXE");
        return prepareRequest(path, token, EXEVIDO);
    }

    public RawRestRequest.Get prepareGetRequestFromExevido(String path) {
        String token = harness.tasks().wso2().authorization().getToken("EXEVIDO_EXE");
        return prepareGetRequest(path, token, EXEVIDO);
    }

    public RawRestRequest.Post prepareRequestFromCvm(String path, boolean addUserIdHeader, String payload) {
        return prepareRequestWithCvm(path, addUserIdHeader, payload, "CVM_SRT");
    }

    public RawRestRequest.Post prepareRequestFromCblToCvm(String path, boolean addUserIdHeader, String payload) {
        return prepareRequestWithCvm(path, addUserIdHeader, payload, "DigitalchannelsSB_CBL");
    }

    public RawRestRequest.Post prepareRequestFromMortgagesToCvm(String path, boolean addUserIdHeader, String payload) {
        return prepareRequestWithCvm(path, addUserIdHeader, payload, "MORTGAGES_HYP");
    }

    public RawRestRequest.Post prepareRequestFromOptimusHubToCvm(String path, boolean addUserIdHeader, String payload) {
        return prepareRequestWithCvm(path, addUserIdHeader, payload, "OPTIMUS_HUB");
    }

    public RawRestRequest.Post prepareRequestFromHubToCvm(String path, boolean addUserIdHeader, String payload) {
        return prepareRequestWithCvm(path, addUserIdHeader, payload, HUB);
    }

    public String getRandomId() {
        return "HARNESS" + UUID.randomUUID().toString().replaceAll("-", "");
    }

    private RawRestRequest.Post prepareRequestWithCvm(String path, boolean addUserIdHeader, String payload, String sourceAppName) {
        String tokenCvmSrt = harness.tasks().wso2().authorization().getToken(sourceAppName);

        RawRestRequest.Request request = harness.withWso2()
                .prepareRequest()
                .withPath("/t/" + path)
                .withHeader("Authorization", tokenCvmSrt)
                .withHeader("Accept", "application/json")
                .withHeader("Content-Type", "application/json")
                .withHeader("activityId", getRandomId())
                .withHeader("requestId", getRandomId());
        if (addUserIdHeader) {
            request = request.withHeader("USERID_L2", "GEBTSRT");
        }
        return request.withPayload(payload);
    }

    private RawRestRequest.Post prepareEmptyRequest(String path, String sourceName, String vaultKey) {
        String token = harness.tasks().wso2().authorization().getToken(vaultKey);
        return prepareRequest(path, token, sourceName, "{}");
    }

    private String getHeader(String source) {
        return "{\"ip-source-application\":\"" + source + "\",\"ip-source-user\":\"\"}";
    }

    private RawRestRequest.Post prepareRequest(String path, String token, String sourceName, String payload) {
        return prepareRequest(path, token, sourceName)
                .withPayload(payload);
    }

    private RawRestRequest.Get prepareGetRequest(String path, String token, String sourceName) {
        return prepareRequest(path, token, sourceName);
    }

    private RawRestRequest.Request prepareRequest(String path, String token, String sourceName) {
        String ufoBanker = AuthSupport.getCredentials(Keys.ufo.banka.banker, harness).getUsername();

        RawRestRequest.Path request = (readTimeout == null) ? harness.withWso2().prepareRequest() : harness.withWso2().prepareRequest(readTimeout);
        return request
                .withPath(path)
                .withHeader("X-IP-Assertion", getHeader(sourceName))
                .withHeader("USERID_L2", ufoBanker)
                .withHeader("Authorization", token)
                .withHeader("Content-Type", "application/json")
                .withHeader("activityId", getRandomId())
                .withHeader("requestId", getRandomId());
    }
}
