package de.krisenvorrat.app.data.remote

import de.krisenvorrat.app.domain.model.ItemFormPrefill
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.bearerAuth
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.addJsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonArray
import kotlinx.serialization.json.putJsonObject
import javax.inject.Inject

internal interface OpenAiVisionService {
    suspend fun analyzeImage(base64Image: String, apiKey: String): List<ItemFormPrefill>
}

internal class OpenAiVisionServiceImpl @Inject constructor(
    private val httpClient: HttpClient
) : OpenAiVisionService {

    override suspend fun analyzeImage(base64Image: String, apiKey: String): List<ItemFormPrefill> {
        return try {
            val requestBody = buildJsonObject {
                put("model", "gpt-4o")
                put("response_format", buildJsonObject { put("type", "json_object") })
                putJsonArray("messages") {
                    addJsonObject {
                        put("role", "user")
                        putJsonArray("content") {
                            addJsonObject {
                                put("type", "text")
                                put("text", RECOGNITION_PROMPT)
                            }
                            addJsonObject {
                                put("type", "image_url")
                                putJsonObject("image_url") {
                                    put("url", "data:image/jpeg;base64,$base64Image")
                                }
                            }
                        }
                    }
                }
            }

            val response: JsonObject = httpClient.post(OPENAI_API_URL) {
                bearerAuth(apiKey)
                contentType(ContentType.Application.Json)
                setBody(requestBody)
            }.body()

            val content = response["choices"]
                ?.jsonArray
                ?.firstOrNull()
                ?.jsonObject
                ?.get("message")
                ?.jsonObject
                ?.get("content")
                ?.jsonPrimitive
                ?.content
                ?: return emptyList()

            val parsed = json.decodeFromString<JsonObject>(content)
            val itemsArray = parsed["items"]?.jsonArray ?: return emptyList()

            itemsArray.mapNotNull { element ->
                try {
                    json.decodeFromJsonElement<ItemFormPrefill>(element)
                } catch (_: Exception) {
                    null
                }
            }
        } catch (_: Exception) {
            emptyList()
        }
    }

    private companion object {
        val json = Json { ignoreUnknownKeys = true }
        const val OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"
        const val RECOGNITION_PROMPT =
            "Erkenne alle Nahrungsmittel und Produkte in diesem Foto. " +
            "Antworte ausschließlich im JSON-Format: " +
            "{\"items\": [{\"name\": \"Produktname\", \"suggestedCategoryName\": \"Kategoriename\", " +
            "\"unit\": \"Einheit\", \"kcalPerKg\": <Int oder null>, \"notes\": \"Zusatzinfos\"}]}. " +
            "Verwende deutsche Produktnamen."
    }
}
