/*
 * Hermes Node Android
 * Copyright (C) 2026 Stefy Lanza <stefy@nexlab.net>
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package net.nexlab.hermesnodeandroid.capabilities

import android.accessibilityservice.AccessibilityService
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.KeyEvent
import net.nexlab.hermesnodeandroid.CapabilityResult
import net.nexlab.hermesnodeandroid.HermesAccessibilityService
import org.json.JSONObject

class AndroidComputerControl(private val context: Context) {
    fun capabilityInfo(): JSONObject = JSONObject()
        .put("available", true)
        .put("platform_semantics", "android_phone_control")
        .put("actions", listOf(
            "launch_app", "open_url", "open_intent", "key_press",
            "tap", "swipe", "long_press", "type_text", "get_active_window",
            "screenshot", "mouse_move", "mouse_click", "mouse_position"
        ).joinToString(","))
        .put("accessibility_available", HermesAccessibilityService.current() != null)
        .put("requires_accessibility_for_input", HermesAccessibilityService.current() == null)
        .put("notes", "Uses Android intents plus AccessibilityService gestures when explicitly enabled by the user")

    fun handle(action: String?, params: JSONObject): CapabilityResult = when (action) {
        "launch_app" -> launchApp(params.optString("package"))
        "open_url" -> openUrl(params.optString("url"))
        "open_intent" -> openIntent(params)
        "key_press" -> keyPress(params.optString("key"))
        "tap", "mouse_click" -> tap(params)
        "mouse_move" -> CapabilityResult.ok("note" to "Android has no persistent pointer; mouse_move is treated as a no-op")
        "swipe" -> swipe(params)
        "long_press" -> longPress(params)
        "type_text" -> typeText(params.optString("text"))
        "get_active_window", "screenshot", "mouse_position" ->
            CapabilityResult.unsupported("$action belongs to AndroidDesktopObserve backend; route via desktop_observe")
        else -> CapabilityResult.unsupported("Unknown computer_control action: $action")
    }

    private fun launchApp(packageName: String): CapabilityResult {
        if (packageName.isBlank()) return CapabilityResult.unsupported("launch_app requires params.package")
        val intent = context.packageManager.getLaunchIntentForPackage(packageName)
            ?: return CapabilityResult.unsupported("No launch intent for package: $packageName")
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
        return CapabilityResult.ok("launched" to packageName)
    }

    private fun openUrl(url: String): CapabilityResult {
        if (url.isBlank()) return CapabilityResult.unsupported("open_url requires params.url")
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
        return CapabilityResult.ok("url" to url)
    }

    private fun openIntent(params: JSONObject): CapabilityResult {
        val action = params.optString("intent_action", Intent.ACTION_VIEW)
        val data = params.optString("data", "")
        val intent = Intent(action).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        if (data.isNotBlank()) intent.data = Uri.parse(data)
        context.startActivity(intent)
        return CapabilityResult.ok("intent_action" to action, "data" to data)
    }

    private fun keyPress(key: String): CapabilityResult {
        val service = accessibility() ?: return CapabilityResult.unsupported("key_press requires enabling Hermes Node Accessibility Service")
        val action = when (key.lowercase()) {
            "back" -> AccessibilityService.GLOBAL_ACTION_BACK
            "home" -> AccessibilityService.GLOBAL_ACTION_HOME
            "recents", "overview" -> AccessibilityService.GLOBAL_ACTION_RECENTS
            "notifications" -> AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS
            "quick_settings" -> AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS
            "power_dialog" -> AccessibilityService.GLOBAL_ACTION_POWER_DIALOG
            "enter" -> return CapabilityResult.unsupported("enter key injection is not available through public Accessibility global actions")
            "volume_up" -> return CapabilityResult.unsupported("volume_up requires privileged input injection; use audio_control/playback APIs instead")
            "volume_down" -> return CapabilityResult.unsupported("volume_down requires privileged input injection; use audio_control/playback APIs instead")
            else -> return CapabilityResult.unsupported("Unsupported Android key: $key")
        }
        return CapabilityResult.ok("key" to key, "performed" to service.globalAction(action))
    }

    private fun tap(params: JSONObject): CapabilityResult {
        val service = accessibility() ?: return CapabilityResult.unsupported("tap requires enabling Hermes Node Accessibility Service")
        val x = params.optInt("x", params.optInt("screen_x", -1))
        val y = params.optInt("y", params.optInt("screen_y", -1))
        if (x < 0 || y < 0) return CapabilityResult.unsupported("tap requires params.x and params.y")
        return CapabilityResult.ok("x" to x, "y" to y, "performed" to service.click(x, y))
    }

    private fun swipe(params: JSONObject): CapabilityResult {
        val service = accessibility() ?: return CapabilityResult.unsupported("swipe requires enabling Hermes Node Accessibility Service")
        val x1 = params.optInt("x1", -1)
        val y1 = params.optInt("y1", -1)
        val x2 = params.optInt("x2", -1)
        val y2 = params.optInt("y2", -1)
        val duration = params.optLong("duration_ms", 300L)
        if (listOf(x1, y1, x2, y2).any { it < 0 }) return CapabilityResult.unsupported("swipe requires x1,y1,x2,y2")
        return CapabilityResult.ok("performed" to service.swipe(x1, y1, x2, y2, duration), "duration_ms" to duration)
    }

    private fun longPress(params: JSONObject): CapabilityResult {
        val service = accessibility() ?: return CapabilityResult.unsupported("long_press requires enabling Hermes Node Accessibility Service")
        val x = params.optInt("x", -1)
        val y = params.optInt("y", -1)
        val duration = params.optLong("duration_ms", 700L)
        if (x < 0 || y < 0) return CapabilityResult.unsupported("long_press requires params.x and params.y")
        return CapabilityResult.ok("x" to x, "y" to y, "performed" to service.longPress(x, y, duration))
    }

    private fun typeText(text: String): CapabilityResult {
        val service = accessibility() ?: return CapabilityResult.unsupported("type_text requires enabling Hermes Node Accessibility Service")
        if (text.isEmpty()) return CapabilityResult.unsupported("type_text requires params.text")
        return CapabilityResult.ok("performed" to service.typeText(text), "length" to text.length)
    }

    private fun accessibility(): HermesAccessibilityService? = HermesAccessibilityService.current()
}
