package eu.mhsl.craftattack.teamLobby.http;

import com.google.gson.*;
import eu.mhsl.craftattack.teamLobby.Main;
import org.apache.http.client.utils.URIBuilder;
import org.spongepowered.configurate.ConfigurationNode;

import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;

public class Request {
    private static final ConfigurationNode apiConfig = Main.getConfig().node("api");
    private static final String websiteEndpoint = apiConfig.node("websiteEndpoint").getString();
    private static final String serverEndpoint = apiConfig.node("serverEndpoint").getString();
    private static final String auth = apiConfig.node("auth").getString();

    private static final URI websiteBasePath = URI.create(Objects.requireNonNull(websiteEndpoint));
    private static final URI serverBasePath = URI.create(Objects.requireNonNull(serverEndpoint) + "/api/");

    private static final Gson gson = new GsonBuilder()
        .registerTypeAdapter(UUID.class, (JsonDeserializer<UUID>) (json, typeOfT, context) -> {
            if (json.isJsonNull() || json.getAsString().isBlank()) {
                return new UUID(0L, 0L);
            }
            return UUID.fromString(json.getAsString());
        })
        .create();

    public static HttpRequest.Builder builder(URI endpoint) {
        return HttpRequest.newBuilder()
            .uri(endpoint)
            .header("User-Agent", "teamLobby minestom")
            .header("Content-Type", "application/json")
            .header("Authorization", auth);
    }

    public static URI website(String command) {
        return website(command, uriBuilder -> {});
    }

    public static URI website(String command, Consumer<URIBuilder> parameters) {
        try {
            URIBuilder builder = new URIBuilder(websiteBasePath + "/" + command);
            parameters.accept(builder);
            return builder.build();
        } catch(URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public static URI server(String command, Consumer<URIBuilder> parameters) {
        try {
            URIBuilder builder = new URIBuilder(serverBasePath + "/" + command);
            parameters.accept(builder);
            return builder.build();
        } catch(URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public static <TResponse> ReqResp<TResponse> execute(HttpRequest request, Type type) {
        ReqResp<String> rawResponse = sendHttp(request);
        System.out.printf("Requesting '%s', got %d with '%s'\n", request.uri(), rawResponse.status(), rawResponse.data());
        return new ReqResp<>(rawResponse.status(), gson.fromJson(rawResponse.data(), type));
    }

    private static ReqResp<String> sendHttp(HttpRequest request) {
        try(HttpClient client = HttpClient.newHttpClient()) {
            HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
            return new ReqResp<>(httpResponse.statusCode(), httpResponse.body());
        } catch(IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
