package com.agentui.desktop

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.speech.RecognizerIntent
import android.util.Log
import android.widget.Toast
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

class VoiceCommandActivity : Activity() {

    companion object {
        private const val TAG = "AgentUI.Voice"
        private const val SPEECH_REQUEST_CODE = 1001
    }

    private val client = OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .build()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Check if launched via share intent
        if (intent?.action == Intent.ACTION_SEND && intent.type == "text/plain") {
            val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
            if (!sharedText.isNullOrBlank()) {
                sendToServer(sharedText)
                return
            }
        }

        // Otherwise, start speech recognition
        startSpeechRecognition()
    }

    private fun startSpeechRecognition() {
        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
            putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
            putExtra(RecognizerIntent.EXTRA_PROMPT, "Agent UI - Speak your command")
        }
        try {
            startActivityForResult(intent, SPEECH_REQUEST_CODE)
        } catch (e: Exception) {
            Toast.makeText(this, "Speech recognition not available", Toast.LENGTH_SHORT).show()
            finish()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == SPEECH_REQUEST_CODE) {
            if (resultCode == RESULT_OK && data != null) {
                val results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
                val text = results?.firstOrNull()
                if (!text.isNullOrBlank()) {
                    sendToServer(text)
                    return
                }
            }
            finish()
        }
    }

    private fun sendToServer(text: String) {
        Thread {
            try {
                val terminalBase = ServerConfig.terminalBaseUrl(this)
                val terminalWs = ServerConfig.terminalWsUrl(this)

                if (terminalBase == null || terminalWs == null) {
                    showToastAndFinish("No server configured")
                    return@Thread
                }

                // 1. Create a new terminal session
                val createBody = JSONObject().apply {
                    put("agent", "ejecutor")
                    put("transcriptSessionId", "__new__")
                    put("label", text.take(60))
                    put("command", "ejecutor")
                }.toString().toRequestBody("application/json".toMediaType())

                val createReq = Request.Builder()
                    .url("$terminalBase/create-terminal")
                    .post(createBody)
                    .build()

                val createResp = client.newCall(createReq).execute()
                if (!createResp.isSuccessful) {
                    showToastAndFinish("Failed to create terminal")
                    return@Thread
                }

                val respJson = JSONObject(createResp.body?.string() ?: "{}")
                val sessionId = respJson.optString("ephemeralSessionId", "")
                if (sessionId.isEmpty()) {
                    showToastAndFinish("No session ID returned")
                    return@Thread
                }

                // 2. Connect via WebSocket and send the input
                val wsUrl = "$terminalWs/ws/terminal?session=$sessionId"
                val wsReq = Request.Builder().url(wsUrl).build()
                val latch = CountDownLatch(1)

                client.newWebSocket(wsReq, object : WebSocketListener() {
                    override fun onOpen(webSocket: WebSocket, response: Response) {
                        // Send the text as input
                        val inputMsg = JSONObject().apply {
                            put("type", "input")
                            put("data", text)
                        }.toString()
                        webSocket.send(inputMsg)

                        // Send Enter key after a short delay
                        Thread.sleep(80)
                        val enterMsg = JSONObject().apply {
                            put("type", "input")
                            put("data", "\r")
                        }.toString()
                        webSocket.send(enterMsg)

                        // Close after sending
                        Thread.sleep(200)
                        webSocket.close(1000, "done")
                        latch.countDown()
                    }

                    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                        Log.e(TAG, "WebSocket failed", t)
                        latch.countDown()
                    }
                })

                latch.await(5, TimeUnit.SECONDS)
                showToastAndFinish("Sent: ${text.take(40)}")

            } catch (e: Exception) {
                Log.e(TAG, "Failed to send command", e)
                showToastAndFinish("Error: ${e.message?.take(40)}")
            }
        }.start()
    }

    private fun showToastAndFinish(message: String) {
        runOnUiThread {
            Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
            finish()
        }
    }
}
