package com.agentui.desktop

import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.widget.RemoteViews
import androidx.work.*
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONArray
import org.json.JSONObject
import java.util.concurrent.TimeUnit

class TranscriptWidgetWorker(
    private val context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    companion object {
        const val WORK_NAME = "transcript_widget_refresh"
        private val MSG_IDS = intArrayOf(
            R.id.msg1, R.id.msg2, R.id.msg3, R.id.msg4, R.id.msg5
        )
        private val client = OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .build()

        fun enqueue(context: Context) {
            val request = OneTimeWorkRequestBuilder<TranscriptWidgetWorker>()
                .build()
            WorkManager.getInstance(context)
                .enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.REPLACE, request)
        }

        fun cancel(context: Context) {
            WorkManager.getInstance(context).cancelUniqueWork(WORK_NAME)
        }
    }

    override suspend fun doWork(): Result {
        val messages = fetchMessages()
        updateWidget(messages)
        scheduleNext()
        return Result.success()
    }

    private fun fetchMessages(): List<String> {
        val apiBase = ServerConfig.apiBaseUrl(context) ?: return listOf("No server configured")

        try {
            // Get most recent session for 'ejecutor' agent
            val sessionsUrl = "$apiBase/transcript-debug/sessions?agent=ejecutor"
            val sessionsReq = Request.Builder().url(sessionsUrl).build()
            val sessionsResp = client.newCall(sessionsReq).execute()
            if (!sessionsResp.isSuccessful) return listOf("Failed to fetch sessions")

            val sessionsJson = JSONArray(sessionsResp.body?.string() ?: "[]")
            if (sessionsJson.length() == 0) return listOf("No sessions found")

            // Get the most recent session (sorted by mtime desc from server)
            val latestSession = sessionsJson.getJSONObject(0)
            val sessionId = latestSession.getString("id")

            // Fetch raw JSONL
            val rawUrl = "$apiBase/transcript-debug/$sessionId/raw?agent=ejecutor"
            val rawReq = Request.Builder().url(rawUrl).build()
            val rawResp = client.newCall(rawReq).execute()
            if (!rawResp.isSuccessful) return listOf("Failed to fetch transcript")

            val rawText = rawResp.body?.string() ?: return listOf("Empty transcript")
            return parseJsonlMessages(rawText)
        } catch (e: Exception) {
            return listOf("Error: ${e.message?.take(40)}")
        }
    }

    private fun parseJsonlMessages(jsonl: String): List<String> {
        val messages = mutableListOf<String>()
        val lines = jsonl.trim().split("\n").filter { it.isNotBlank() }

        for (line in lines) {
            try {
                val obj = JSONObject(line)
                val type = obj.optString("type", "")

                when (type) {
                    "human" -> {
                        val content = obj.optString("message", "")
                            .ifEmpty { extractMessageContent(obj) }
                        if (content.isNotEmpty()) {
                            messages.add("> ${content.take(80)}")
                        }
                    }
                    "assistant" -> {
                        val content = extractMessageContent(obj)
                        if (content.isNotEmpty()) {
                            messages.add("< ${content.take(80)}")
                        }
                    }
                }
            } catch (_: Exception) { }
        }

        return messages.takeLast(5).ifEmpty { listOf("No messages yet") }
    }

    private fun extractMessageContent(obj: JSONObject): String {
        // Try "message" field first (simple string)
        val msg = obj.optString("message", "")
        if (msg.isNotEmpty()) return msg

        // Try "message" as array of content blocks
        val msgArray = obj.optJSONArray("message")
        if (msgArray != null) {
            for (i in 0 until msgArray.length()) {
                val block = msgArray.optJSONObject(i) ?: continue
                if (block.optString("type") == "text") {
                    return block.optString("text", "")
                }
            }
        }

        return ""
    }

    private fun updateWidget(messages: List<String>) {
        val views = RemoteViews(context.packageName, R.layout.widget_transcript)

        for (i in MSG_IDS.indices) {
            views.setTextViewText(MSG_IDS[i], messages.getOrElse(i) { "" })
        }

        val appWidgetManager = AppWidgetManager.getInstance(context)
        val widgetComponent = ComponentName(context, TranscriptWidgetProvider::class.java)
        appWidgetManager.updateAppWidget(widgetComponent, views)
    }

    private fun scheduleNext() {
        val request = OneTimeWorkRequestBuilder<TranscriptWidgetWorker>()
            .setInitialDelay(30, TimeUnit.SECONDS)
            .build()
        WorkManager.getInstance(context)
            .enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.REPLACE, request)
    }
}
