/*
 * Ollama4j - Java library for interacting with Ollama server.
 * Copyright (c) 2025 Amith Koujalgi and contributors.
 *
 * Licensed under the MIT License (the "License");
 * you may not use this file except in compliance with the License.
 *
*/
package io.github.ollama4j.models.response;

import static io.github.ollama4j.utils.Utils.getObjectMapper;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.List;
import java.util.Map;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@SuppressWarnings("unused")
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class OllamaStructuredResult {
    private String response;
    private String thinking;
    private int httpStatusCode;
    private long responseTime = 0;
    private String model;

    private @JsonProperty("created_at") String createdAt;
    private boolean done;
    private @JsonProperty("done_reason") String doneReason;
    private List<Integer> context;
    private @JsonProperty("total_duration") Long totalDuration;
    private @JsonProperty("load_duration") Long loadDuration;
    private @JsonProperty("prompt_eval_count") Integer promptEvalCount;
    private @JsonProperty("prompt_eval_duration") Long promptEvalDuration;
    private @JsonProperty("eval_count") Integer evalCount;
    private @JsonProperty("eval_duration") Long evalDuration;

    public OllamaStructuredResult(String response, long responseTime, int httpStatusCode) {
        this.response = response;
        this.responseTime = responseTime;
        this.httpStatusCode = httpStatusCode;
    }

    @Override
    public String toString() {
        try {
            return getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(this);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Get the structured response if the response is a JSON object.
     *
     * @return Map - structured response
     */
    public Map<String, Object> getStructuredResponse() {
        try {
            return getObjectMapper()
                    .readValue(this.getResponse(), new TypeReference<Map<String, Object>>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Get the structured response mapped to a specific class type.
     *
     * @param <T>   The type of class to map the response to
     * @param clazz The class to map the response to
     * @return An instance of the specified class with the response data
     * @throws RuntimeException if there is an error mapping the response
     */
    public <T> T getStructuredResponse(Class<T> clazz) {
        try {
            return getObjectMapper().readValue(this.getResponse(), clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
