package env;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import cartago.Artifact;
import cartago.OPERATION;

public class SentimentArtifact extends Artifact {

    /* You need to create an API_KEY at: https://aistudio.google.com/api-keys */
    private static final String API_KEY = "NONE";
    private static final String MODEL = "gemini-2.5-flash";
    private static final String GEMINI_URL =
            "https://generativelanguage.googleapis.com/v1beta/models/"
                    + MODEL + ":generateContent?key=" + API_KEY;

    private final List<String> replies = new ArrayList<>();

    void init() {
        System.out.println("✅ SentimentArtifact inicializado");
    }

    @OPERATION
    public void clearReplies() {
        replies.clear();
    }

    @OPERATION
    public void addReply(String text) {
        if (text != null && !text.trim().isEmpty()) {
            replies.add(text.trim());
        }
    }

    @OPERATION
    public void clearResults() {
        while (getObsProperty("sentiment_result") != null) {
            removeObsProperty("sentiment_result");
        }
        while (getObsProperty("analysis_count") != null) {
            removeObsProperty("analysis_count");
        }
    }

    @OPERATION
    public void analyze() {
        System.out.println("📊 Analisando sentimentos...");

        clearResults();

        if (replies.isEmpty()) {
            defineObsProperty("analysis_count", 0);
            signal("analysis_done");
            return;
        }

        List<String> limitedReplies = replies.size() > 20
                ? replies.subList(0, 20)
                : new ArrayList<>(replies);

        StringBuilder repliesBlock = new StringBuilder();
        for (int i = 0; i < limitedReplies.size(); i++) {
            repliesBlock.append(i + 1)
                    .append(". ")
                    .append(limitedReplies.get(i))
                    .append("\n");
        }

        String prompt =
                "Classify each reply as: positive, negative, or neutral.\n\n" +
                "Rules:\n" +
                "- Positive: praise, support, enthusiasm\n" +
                "- Negative: criticism, insults, disagreement, hostility\n" +
                "- Neutral: factual or unclear tone\n\n" +
                "Return ONLY JSON:\n\n" +
                "{\n" +
                "  \"sentiments\": [\"positive\", \"negative\", \"neutral\"]\n" +
                "}\n\n" +
                "Replies:\n" +
                repliesBlock;

        try {
            String raw = callGemini(prompt);

            System.out.println("LLM RAW: " + raw);

            String cleaned = raw
                    .replace("```json", "")
                    .replace("```", "")
                    .trim();

            JSONObject parsed = new JSONObject(cleaned);
            JSONArray sentiments = parsed.getJSONArray("sentiments");

            defineObsProperty("analysis_count", sentiments.length());

            for (int i = 0; i < sentiments.length(); i++) {
                String normalized = sentiments.getString(i)
                        .toLowerCase()
                        .replaceAll("[^a-z]", "");

                String sentiment;
                if ("positive".equals(normalized)) sentiment = "positive";
                else if ("negative".equals(normalized)) sentiment = "negative";
                else sentiment = "neutral";

                defineObsProperty("sentiment_result", i + 1, sentiment);
            }

            signal("analysis_done");

        } catch (Exception error) {
            System.out.println("❌ Erro ao processar resposta da LLM: " + error.getMessage());

            defineObsProperty("analysis_count", limitedReplies.size());

            for (int i = 0; i < limitedReplies.size(); i++) {
                defineObsProperty("sentiment_result", i + 1, "neutral");
            }

            signal("analysis_done");
        }
    }

    private String callGemini(String prompt) throws Exception {
        if (API_KEY == null || API_KEY.isBlank()) {
            throw new RuntimeException("GEMINI_API_KEY não definida.");
        }

        URL url = new URL(GEMINI_URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        conn.setDoOutput(true);

        JSONObject textPart = new JSONObject();
        textPart.put("text", prompt);

        JSONArray parts = new JSONArray();
        parts.put(textPart);

        JSONObject content = new JSONObject();
        content.put("parts", parts);

        JSONArray contents = new JSONArray();
        contents.put(content);

        JSONObject body = new JSONObject();
        body.put("contents", contents);

        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = body.toString().getBytes(StandardCharsets.UTF_8);
            os.write(input);
        }

        int status = conn.getResponseCode();

        BufferedReader reader;
        if (status >= 200 && status < 300) {
            reader = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)
            );
        } else {
            reader = new BufferedReader(
                    new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8)
            );
        }

        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }

        reader.close();
        conn.disconnect();

        if (status < 200 || status >= 300) {
            throw new RuntimeException("HTTP " + status + ": " + response);
        }

        JSONObject json = new JSONObject(response.toString());
        JSONArray candidates = json.optJSONArray("candidates");

        if (candidates == null || candidates.length() == 0) {
            throw new RuntimeException("Resposta sem candidates: " + response);
        }

        JSONObject first = candidates.getJSONObject(0);
        JSONObject contentObj = first.getJSONObject("content");
        JSONArray responseParts = contentObj.getJSONArray("parts");

        if (responseParts.length() == 0) {
            throw new RuntimeException("Resposta sem parts: " + response);
        }

        return responseParts.getJSONObject(0).optString("text", "");
    }
}