package com.correx.core.kernel.orchestration

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive

/**
 * Pulls the workspace-relative file-path references out of an LLM-emitted brief artifact (JSON),
 * for entity grounding (role-reliability §3). Deterministic: walks every string leaf, splits on
 * whitespace, strips surrounding prose punctuation, and keeps tokens that read as a relative
 * file path — one containing a '/' and ending in a short dotted extension.
 *
 * Module/subsystem names, bare words, URLs, and absolute or parent-relative paths are
 * intentionally skipped. Only concrete file references are grounded, so the check catches
 * hallucinated paths ("analysts hallucinate paths the same as planners") without false-flagging
 * the coarse "files, modules, or subsystems" the brief is allowed to name.
 */
internal object BriefReferenceExtractor {

    // <segments…>/<name>.<ext>: at least one slash, a final dotted extension of 1–5 letters/digits.
    private val FILE_REF = Regex("""^[A-Za-z0-9_.\-/]+/[A-Za-z0-9_.\-]+\.[A-Za-z][A-Za-z0-9]{0,4}$""")

    fun fileReferences(artifactJson: String): List<String> {
        val root = runCatching { Json.parseToJsonElement(artifactJson) }.getOrNull() ?: return emptyList()
        val out = LinkedHashSet<String>()
        collectStrings(root) { value ->
            for (token in value.split(WHITESPACE)) {
                val cleaned = token
                    .trimStart('(', '[', '{', '`', '"', '\'')
                    .trimEnd(')', ']', '}', ',', '.', ';', ':', '`', '"', '\'')
                if (cleaned.isFileReference()) out += cleaned
            }
        }
        return out.toList()
    }

    private fun String.isFileReference(): Boolean =
        !startsWith("/") && !contains("..") && !contains("://") && FILE_REF.matches(this)

    private fun collectStrings(element: JsonElement, sink: (String) -> Unit) {
        when (element) {
            is JsonPrimitive -> if (element.isString) sink(element.content)
            is JsonArray -> element.forEach { collectStrings(it, sink) }
            is JsonObject -> element.values.forEach { collectStrings(it, sink) }
        }
    }

    private val WHITESPACE = Regex("""\s+""")
}
