package com.agentui.desktop

import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import android.widget.RemoteViews

class InputWidgetProvider : AppWidgetProvider() {

    companion object {
        private const val TAG = "InputWidget"

        const val ACTION_SEND = "com.agentui.desktop.INPUT_WIDGET_SEND"
        const val ACTION_MIC = "com.agentui.desktop.INPUT_WIDGET_MIC"
        const val ACTION_CANCEL = "com.agentui.desktop.INPUT_WIDGET_CANCEL"

        private const val STATE_IDLE = 0
        private const val STATE_SENDING = 1
        private const val STATE_PROCESSING = 2
        private const val STATE_DONE = 3
        private const val STATE_ERROR = 4

        private const val PREFS_NAME = "input_widget_prefs"
        private const val KEY_STATE = "hook_state"

        // Colors
        private const val COLOR_IDLE = 0x8040C040.toInt()
        private const val COLOR_SENDING = 0xFF60a5fa.toInt()
        private const val COLOR_PROCESSING = 0xFFfbbf24.toInt()
        private const val COLOR_DONE = 0xFF4ade80.toInt()
        private const val COLOR_ERROR = 0xFFf87171.toInt()

        private const val COLOR_BTN_ACTIVE = 0xEEFFFFFF.toInt()
        private const val COLOR_BTN_NORMAL = 0xAAFFFFFF.toInt()
        private const val COLOR_BTN_DIM = 0x50FFFFFF.toInt()
        private const val COLOR_TEXT_DIM = 0x80FFFFFF.toInt()

        private val STATUS_LABELS = mapOf(
            STATE_IDLE to "idle",
            STATE_SENDING to "sending...",
            STATE_PROCESSING to "processing...",
            STATE_DONE to "done",
            STATE_ERROR to "error"
        )
    }

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        Log.d(TAG, "onUpdate called for ${appWidgetIds.size} widgets")
        for (id in appWidgetIds) {
            updateWidget(context, appWidgetManager, id)
        }
    }

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)

        Log.d(TAG, "onReceive: action=${intent.action}")

        when (intent.action) {
            ACTION_SEND -> {
                val next = when (getState(context)) {
                    STATE_IDLE -> STATE_SENDING
                    STATE_SENDING -> STATE_PROCESSING
                    STATE_PROCESSING -> STATE_DONE
                    else -> STATE_IDLE
                }
                Log.d(TAG, "SEND: state -> $next")
                setState(context, next)
                refreshAll(context)
            }
            ACTION_MIC -> {
                val next = if (getState(context) == STATE_IDLE) STATE_SENDING else STATE_IDLE
                Log.d(TAG, "MIC: state -> $next")
                setState(context, next)
                refreshAll(context)
            }
            ACTION_CANCEL -> {
                val current = getState(context)
                val next = when (current) {
                    STATE_SENDING, STATE_PROCESSING -> STATE_ERROR
                    else -> STATE_IDLE
                }
                Log.d(TAG, "CANCEL: state -> $next")
                setState(context, next)
                refreshAll(context)
            }
        }
    }

    private fun updateWidget(context: Context, mgr: AppWidgetManager, id: Int) {
        val views = RemoteViews(context.packageName, R.layout.widget_input)
        val state = getState(context)

        // Open app — only the ↗ button
        val appIntent = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK
        }
        val appPending = PendingIntent.getActivity(
            context, 100, appIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        views.setOnClickPendingIntent(R.id.btn_open_app, appPending)

        // Input field → send
        views.setOnClickPendingIntent(R.id.input_field,
            makeBroadcast(context, ACTION_SEND, "input_field"))

        // Buttons — each with unique data URI to avoid PendingIntent deduplication
        views.setOnClickPendingIntent(R.id.btn_send,
            makeBroadcast(context, ACTION_SEND, "btn_send"))
        views.setOnClickPendingIntent(R.id.btn_mic,
            makeBroadcast(context, ACTION_MIC, "btn_mic"))
        views.setOnClickPendingIntent(R.id.btn_cancel,
            makeBroadcast(context, ACTION_CANCEL, "btn_cancel"))

        applyState(views, state)
        mgr.updateAppWidget(id, views)
    }

    /**
     * Create a unique PendingIntent per button using data URI differentiation.
     * This prevents Android from deduplicating PendingIntents that share the same action.
     */
    private fun makeBroadcast(context: Context, action: String, tag: String): PendingIntent {
        val intent = Intent(action).apply {
            component = ComponentName(context, InputWidgetProvider::class.java)
            data = Uri.parse("agentui://input-widget/$tag")
        }
        return PendingIntent.getBroadcast(
            context, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
        )
    }

    private fun applyState(views: RemoteViews, state: Int) {
        val stateColor = when (state) {
            STATE_IDLE -> COLOR_IDLE
            STATE_SENDING -> COLOR_SENDING
            STATE_PROCESSING -> COLOR_PROCESSING
            STATE_DONE -> COLOR_DONE
            STATE_ERROR -> COLOR_ERROR
            else -> COLOR_IDLE
        }

        // Status dot
        val dotGlyph = when (state) {
            STATE_SENDING, STATE_PROCESSING -> "\u25CC"
            else -> "\u25CF"
        }
        views.setTextViewText(R.id.input_status_dot, dotGlyph)
        views.setTextColor(R.id.input_status_dot, stateColor)

        // Status text
        views.setTextViewText(R.id.input_status_text, STATUS_LABELS[state] ?: "idle")
        views.setTextColor(R.id.input_status_text, stateColor)

        // Input field prompt
        val prompt = when (state) {
            STATE_IDLE -> "$ _"
            STATE_SENDING -> "$ sending..."
            STATE_PROCESSING -> "$ processing..."
            STATE_DONE -> "$ done \u2713"
            STATE_ERROR -> "$ error \u26A0"
            else -> "$ _"
        }
        views.setTextViewText(R.id.input_field, prompt)
        views.setTextColor(R.id.input_field, when (state) {
            STATE_IDLE -> COLOR_TEXT_DIM
            else -> stateColor
        })

        // Send button
        views.setTextColor(R.id.btn_send, when (state) {
            STATE_IDLE -> COLOR_BTN_ACTIVE
            STATE_DONE, STATE_ERROR -> COLOR_BTN_NORMAL
            else -> COLOR_BTN_DIM
        })

        // Mic button
        views.setTextColor(R.id.btn_mic, when (state) {
            STATE_IDLE -> COLOR_BTN_NORMAL
            STATE_SENDING -> COLOR_SENDING
            else -> COLOR_BTN_DIM
        })

        // Cancel button
        views.setTextColor(R.id.btn_cancel, when (state) {
            STATE_SENDING, STATE_PROCESSING -> COLOR_ERROR
            else -> COLOR_BTN_DIM
        })
    }

    private fun getState(context: Context): Int =
        context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            .getInt(KEY_STATE, STATE_IDLE)

    private fun setState(context: Context, state: Int) {
        context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            .edit().putInt(KEY_STATE, state).apply()
    }

    private fun refreshAll(context: Context) {
        val mgr = AppWidgetManager.getInstance(context)
        val ids = mgr.getAppWidgetIds(ComponentName(context, InputWidgetProvider::class.java))
        Log.d(TAG, "refreshAll: ${ids.size} widgets")
        for (id in ids) updateWidget(context, mgr, id)
    }
}
