package org.dbis.iru;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * DBIS IRU Java Client
 */
public class IRUClient {
    private final String apiBaseUrl;
    private final String apiKey;
    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;

    public IRUClient(String apiBaseUrl, String apiKey) {
        this.apiBaseUrl = apiBaseUrl.replaceAll("/$", "");
        this.apiKey = apiKey;
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30))
            .build();
        this.objectMapper = new ObjectMapper();
    }

    /**
     * Get all IRU offerings
     */
    public CompletableFuture<List<IRUOffering>> getOfferings(
        Integer capacityTier,
        String institutionalType
    ) {
        StringBuilder url = new StringBuilder(apiBaseUrl + "/api/v1/iru/marketplace/offerings");
        boolean hasParams = false;
        
        if (capacityTier != null) {
            url.append(hasParams ? "&" : "?").append("capacityTier=").append(capacityTier);
            hasParams = true;
        }
        if (institutionalType != null) {
            url.append(hasParams ? "&" : "?").append("institutionalType=").append(institutionalType);
        }

        return request("GET", url.toString(), null)
            .thenApply(response -> {
                try {
                    Map<String, Object> json = objectMapper.readValue(response, Map.class);
                    Map<String, Object> data = (Map<String, Object>) json.get("data");
                    List<Map<String, Object>> offerings = (List<Map<String, Object>>) data.get("data");
                    // Convert to IRUOffering objects
                    return offerings.stream()
                        .map(this::mapToOffering)
                        .collect(java.util.stream.Collectors.toList());
                } catch (Exception e) {
                    throw new RuntimeException("Failed to parse response", e);
                }
            });
    }

    /**
     * Submit inquiry
     */
    public CompletableFuture<InquiryResult> submitInquiry(IRUInquiry inquiry) {
        try {
            String body = objectMapper.writeValueAsString(inquiry.toMap());
            return request("POST", apiBaseUrl + "/api/v1/iru/marketplace/inquiries", body)
                .thenApply(response -> {
                    try {
                        Map<String, Object> json = objectMapper.readValue(response, Map.class);
                        Map<String, Object> data = (Map<String, Object>) json.get("data");
                        return new InquiryResult(
                            (String) data.get("inquiryId"),
                            (String) data.get("status"),
                            (String) data.get("message")
                        );
                    } catch (Exception e) {
                        throw new RuntimeException("Failed to parse response", e);
                    }
                });
        } catch (Exception e) {
            return CompletableFuture.failedFuture(e);
        }
    }

    private CompletableFuture<String> request(String method, String url, String body) {
        HttpRequest.Builder builder = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .timeout(Duration.ofSeconds(30))
            .header("Content-Type", "application/json");

        if (apiKey != null) {
            builder.header("Authorization", "Bearer " + apiKey);
        }

        if (body != null) {
            builder.method(method, HttpRequest.BodyPublishers.ofString(body));
        } else {
            builder.method(method, HttpRequest.BodyPublishers.noBody());
        }

        return httpClient.sendAsync(builder.build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body);
    }

    private IRUOffering mapToOffering(Map<String, Object> map) {
        return new IRUOffering(
            (String) map.get("id"),
            (String) map.get("offeringId"),
            (String) map.get("name"),
            (String) map.get("description"),
            ((Number) map.get("capacityTier")).intValue(),
            (String) map.get("institutionalType"),
            map.get("basePrice") != null ? ((Number) map.get("basePrice")).doubleValue() : null,
            (String) map.get("currency")
        );
    }
}
