package it.com.atlassian.bitbucket.mirror;

import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.atlassian.pageobjects.ProductInstance;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import java.io.IOException;
import java.net.URI;
import java.util.function.Function;

public class MirrorTestUtils {

    private static UsernamePasswordCredentials ADMIN_CREDENTIALS = new UsernamePasswordCredentials(
            DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword());

    private MirrorTestUtils() {
    }

    public static void setDevMode(ProductInstance instance, boolean enabled) throws IOException {
        HttpPut put = new HttpPut(instance.getBaseUrl() + "/rest/mirror-setup-test/latest/test-support/dev-mode/" + enabled);
        StatusLine status = executeAsAdmin(put, HttpResponse::getStatusLine);
        int statusCode = status.getStatusCode();
        if (statusCode < 200 || statusCode >= 300) {
            throw new IllegalStateException("Request failed: " + status);
        }
    }

    private static <T> T executeAsAdmin(HttpUriRequest method, Function<HttpResponse, T> callback) {
        try (CloseableHttpClient httpclient = HttpClientBuilder.create().build()) {
            URI uri = method.getURI();
            HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), ADMIN_CREDENTIALS);

            AuthCache authCache = new BasicAuthCache();
            BasicScheme basicAuth = new BasicScheme();
            authCache.put(targetHost, basicAuth);

            HttpClientContext context = HttpClientContext.create();
            context.setCredentialsProvider(credsProvider);
            context.setAuthCache(authCache);

            try (CloseableHttpResponse response = httpclient.execute(targetHost, method, context)) {
                return callback.apply(response);
            }
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }
}
