package core

/**
 * Representa un interes del usuario con nombre, keywords y peso.
 */
data class Interest(
    val name: String,
    val keywords: List<String> = emptyList(),
    val weight: Double = 1.0
)

/**
 * Mensaje en formato OpenAI/Ollama para conversaciones con LLMs.
 */
data class ChatMessage(
    val role: String,  // "system" | "user" | "assistant"
    val content: String
)

/**
 * buildGuidePrompt construye un prompt contextual para el LLM como guía local.
 *
 * Combina la ubicación actual del usuario, POIs cercanos rankeados por relevancia
 * e intereses del usuario para generar mensajes en formato OpenAI/Ollama.
 *
 * @param location Mapa con info de ubicación (nominatim reverse geocode).
 *                 Campos esperados: display_name, street, neighbourhood, city, country, etc.
 * @param pois Lista de POIs rankeados. Cada mapa contiene: name, category, score,
 *             matched_interests (List<String>), lat, lon, tags. Ya filtrados y ordenados.
 * @param interests Lista de intereses del usuario.
 * @param userQuery Pregunta opcional del usuario. Si está vacía, se usa un default.
 * @param lang Idioma para la respuesta del LLM (ej: "es", "en", "fr").
 * @return Lista de dos ChatMessage: [system, user].
 */
fun buildGuidePrompt(
    location: Map<String, String>,
    pois: List<Map<String, Any>>,
    interests: List<Interest>,
    userQuery: String = "",
    lang: String = "es"
): List<ChatMessage> {
    // Extraer nombre de intereses para el system prompt
    val interestsStr = if (interests.isNotEmpty()) {
        interests.filter { it.name.isNotEmpty() }.joinToString(", ") { it.name }
            .ifEmpty { "lugares de interés general" }
    } else {
        "lugares de interés general"
    }

    // Extraer ciudad para el system prompt
    val city = location["city"]?.takeIf { it.isNotEmpty() }
        ?: location["town"]?.takeIf { it.isNotEmpty() }
        ?: location["village"]?.takeIf { it.isNotEmpty() }
        ?: "tu zona"

    // Construir system message
    val systemContent = buildString {
        append("Eres un guía local experto y amigable. El usuario está caminando por $city ")
        append("y le interesan: $interestsStr.\n")
        append("Tu objetivo es informar sobre lo que hay cerca, dar contexto histórico/cultural ")
        append("relevante a sus intereses, y sugerir qué visitar.\n")
        append("Responde en $lang. Sé conciso (máximo 3-4 frases) y conversacional, ")
        append("como si caminaras junto al usuario.\n")
        append("Si no hay POIs relevantes, comenta sobre el barrio o zona.")
    }

    // Construir user message
    val userParts = mutableListOf<String>()

    // Ubicación
    val displayName = location["display_name"] ?: ""
    if (displayName.isNotEmpty()) {
        userParts.add("📍 Estoy en: $displayName")
    }

    val neighbourhood = location["neighbourhood"]?.takeIf { it.isNotEmpty() }
        ?: location["suburb"]?.takeIf { it.isNotEmpty() }
        ?: ""
    val cityLabel = location["city"]?.takeIf { it.isNotEmpty() }
        ?: location["town"]?.takeIf { it.isNotEmpty() }
        ?: location["village"]?.takeIf { it.isNotEmpty() }
        ?: ""
    val locationLineParts = listOf(neighbourhood, cityLabel).filter { it.isNotEmpty() }
    if (locationLineParts.isNotEmpty()) {
        userParts.add("Barrio: ${locationLineParts.joinToString(", ")}")
    }

    // POIs (máximo 5)
    val topPois = pois.take(5)
    if (topPois.isNotEmpty()) {
        userParts.add("")
        userParts.add("Lugares cercanos que me pueden interesar:")
        for (poi in topPois) {
            val name = poi["name"] as? String ?: "Sin nombre"
            val category = poi["category"] as? String ?: ""
            @Suppress("UNCHECKED_CAST")
            val matched = poi["matched_interests"] as? List<String> ?: emptyList()
            val matchedStr = matched.joinToString(", ")

            val poiLine = buildString {
                append("- $name")
                if (category.isNotEmpty()) append(" ($category)")
                if (matchedStr.isNotEmpty()) append(" — relevante para: $matchedStr")
            }
            userParts.add(poiLine)
        }
    }

    // Query del usuario
    userParts.add("")
    val trimmedQuery = userQuery.trim()
    userParts.add(if (trimmedQuery.isNotEmpty()) trimmedQuery else "¿Qué me puedes contar de esta zona?")

    val userContent = userParts.joinToString("\n")

    return listOf(
        ChatMessage(role = "system", content = systemContent),
        ChatMessage(role = "user", content = userContent)
    )
}
