package com.correx.core.events.events

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

/**
 * Parses an optional `questions` array out of an LLM artifact's JSON body (e.g. the analyst's
 * analysis). Lenient and fence-tolerant: any parse failure, or an absent/empty array, yields an
 * empty list (meaning "no clarification needed"). Each element needs at least a prompt (accepts
 * `prompt` or `question`); `id`/`options`/`multiSelect`/`header` are optional, matching the analyst
 * prompt convention. Lives next to [ClarificationQuestion] so the orchestrator and the server parse
 * questions identically.
 */
object ClarificationQuestions {

    private val json = Json { ignoreUnknownKeys = true; isLenient = true }

    fun parse(content: String): List<ClarificationQuestion> = runCatching {
        val root = json.parseToJsonElement(stripFence(content)).jsonObject
        val array = root["questions"]?.jsonArray ?: return emptyList()
        array.mapIndexedNotNull { index, element ->
            val obj = element as? JsonObject ?: return@mapIndexedNotNull null
            val prompt = (obj["prompt"] ?: obj["question"])?.jsonPrimitive?.contentOrNull
                ?: return@mapIndexedNotNull null
            ClarificationQuestion(
                id = obj["id"]?.jsonPrimitive?.contentOrNull ?: "q${index + 1}",
                prompt = prompt,
                options = obj["options"]?.jsonArray?.mapNotNull { it.jsonPrimitive.contentOrNull } ?: emptyList(),
                multiSelect = obj["multiSelect"]?.jsonPrimitive?.booleanOrNull ?: false,
                header = obj["header"]?.jsonPrimitive?.contentOrNull ?: "",
            )
        }
    }.getOrElse { emptyList() }

    /** Drops a single outer ```` ```lang … ``` ```` fence when the whole body is one fenced block. */
    private fun stripFence(text: String): String {
        val trimmed = text.trim()
        if (!trimmed.startsWith("```") || !trimmed.endsWith("```")) return text
        val withoutClose = trimmed.removeSuffix("```").trimEnd()
        val firstNewline = withoutClose.indexOf('\n')
        return if (firstNewline < 0) text else withoutClose.substring(firstNewline + 1)
    }
}
