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.security.MessageDigest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class WhiteholeOpenApiExample {
    private static final String BASE_URL = envOrDefault("WH_OPEN_API_BASE_URL", "https://open.whbdvr.com");
    private static final String APP_KEY = envOrDefault("WH_OPEN_API_APP_KEY", "replace-with-app-key");
    private static final String APP_SECRET = envOrDefault("WH_OPEN_API_APP_SECRET", "replace-with-app-secret");
    private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();

    public static void main(String[] args) throws Exception {
        String tenantProfile = requestOpenApi("GET", "/api/external/open-api/tenant/profile");
        String orders = requestOpenApi("GET", "/api/external/open-api/orders");
        String businessTrend = requestOpenApi("GET", "/api/external/open-api/reports/business-trend");
        String productSalesRanking = requestOpenApi("GET", "/api/external/open-api/reports/product-sales-ranking");
        String memberGrowthRetention = requestOpenApi("GET", "/api/external/open-api/reports/member-growth-retention");
        String businessMetricGroups = requestOpenApi("GET", "/api/external/open-api/reports/business-metric-groups");

        System.out.println("tenantProfile:");
        System.out.println(tenantProfile);
        System.out.println("orders:");
        System.out.println(orders);
        System.out.println("businessTrend:");
        System.out.println(businessTrend);
        System.out.println("productSalesRanking:");
        System.out.println(productSalesRanking);
        System.out.println("memberGrowthRetention:");
        System.out.println(memberGrowthRetention);
        System.out.println("businessMetricGroups:");
        System.out.println(businessMetricGroups);
    }

    private static String requestOpenApi(String method, String path) throws Exception {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String signature = signOpenApiRequest(method, path, timestamp);
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(BASE_URL + path))
            .method(method.toUpperCase(), HttpRequest.BodyPublishers.noBody())
            .header("X-WH-App-Key", APP_KEY)
            .header("X-WH-Timestamp", timestamp)
            .header("X-WH-Signature", signature)
            .build();

        HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new IOException("Open API request failed: " + response.statusCode() + " " + response.body());
        }
        return response.body();
    }

    private static String signOpenApiRequest(String method, String path, String timestamp) throws Exception {
        String signingKey = sha256Hex(APP_SECRET);
        String payload = method.toUpperCase() + "\n" + path + "\n" + timestamp;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(signingKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        return hex(mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)));
    }

    private static String sha256Hex(String value) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        return hex(digest.digest(value.getBytes(StandardCharsets.UTF_8)));
    }

    private static String hex(byte[] bytes) {
        StringBuilder result = new StringBuilder(bytes.length * 2);
        for (byte item : bytes) {
            result.append(String.format("%02x", item));
        }
        return result.toString();
    }

    private static String envOrDefault(String key, String fallback) {
        String value = System.getenv(key);
        return value == null || value.isBlank() ? fallback : value;
    }
}
