package at.procon.dip.embedding.provider.http;

import at.procon.dip.embedding.model.ResolvedEmbeddingProviderConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
abstract class AbstractHttpEmbeddingProviderSupport {

    protected final ObjectMapper objectMapper;
    protected final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .build();

    protected String trimTrailingSlash(String value) {
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException("Embedding provider baseUrl must be configured");
        }
        return value.endsWith("/") ? value.substring(0, value.length() - 1) : value;
    }

    protected HttpResponse<String> postJson(ResolvedEmbeddingProviderConfig providerConfig,
                                            String path,
                                            Object body) throws IOException, InterruptedException {
        HttpRequest.Builder builder = HttpRequest.newBuilder()
                .uri(URI.create(trimTrailingSlash(providerConfig.baseUrl()) + path))
                .timeout(providerConfig.readTimeout() == null ? Duration.ofSeconds(60) : providerConfig.readTimeout())
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(
                        objectMapper.writeValueAsString(body),
                        StandardCharsets.UTF_8
                ));

        if (providerConfig.apiKey() != null && !providerConfig.apiKey().isBlank()) {
            builder.header("Authorization", "Bearer " + providerConfig.apiKey());
        }
        if (providerConfig.headers() != null) {
            providerConfig.headers().forEach(builder::header);
        }

        HttpResponse<String> response = httpClient.send(
                builder.build(),
                HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)
        );
        if (response.statusCode() / 100 != 2) {
            throw new IllegalStateException(
                    "Embedding provider returned status %d: %s".formatted(response.statusCode(), response.body())
            );
        }
        return response;
    }

    protected float[] toArray(List<Float> embedding) {
        float[] result = new float[embedding.size()];
        for (int i = 0; i < embedding.size(); i++) {
            result[i] = embedding.get(i);
        }
        return result;
    }
}
