package com.beancount.mobile.accessibility

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView

/**
 * 记账助手悬浮球（边缘竖线胶囊面板）。
 * 贴合在屏幕边缘，采用高透、超轻量竖线指示器，点击后展开垂直对齐的功能菜单。
 */
class FloatingHelper(
    private val service: SelectToSpeakService
) {
    companion object {
        private const val TAG = "FloatingHelper"
        private const val PREFS_NAME = "billing_accessibility_prefs"
        private const val KEY_X = "floating_ball_x"
        private const val KEY_Y = "floating_ball_y"
        private var lastX = 0
        private var lastY = 400
    }

    private val windowManager = service.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    private var containerView: LinearLayout? = null
    private var bubbleView: View? = null
    private var menuView: LinearLayout? = null
    private var isExpanded = false

    private val params = WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
        PixelFormat.TRANSLUCENT
    ).apply {
        gravity = Gravity.TOP or Gravity.START
        x = lastX
        y = lastY
    }

    @SuppressLint("ClickableViewAccessibility")
    fun show() {
        if (containerView != null) return

        try {
            val context = service

            // 加载浮层 UI 配置（颜色与文案均从 JS 下发的 config 读取，未下发时回退默认值）
            val config = FloatingUiConfigStore.load(service)

            // 预解析颜色
            val colorAccent = FloatingUiConfigStore.parseColorOr(config.colors.accent, "#FF5E6AD2")
            val colorAccentFg = FloatingUiConfigStore.parseColorOr(config.colors.accentFg, "#FFFFFFFF")
            val colorCardBg = FloatingUiConfigStore.parseColorOr(config.colors.cardBg, "#F0050506")
            val colorFgPrimary = FloatingUiConfigStore.parseColorOr(config.colors.fgPrimary, "#FFFFFFFF")
            val colorFgSecondary = FloatingUiConfigStore.parseColorOr(config.colors.fgSecondary, "#FF9CA3AF")
            val colorBorder = FloatingUiConfigStore.parseColorOr(config.colors.border, "#80222433")
            val colorInputBg = FloatingUiConfigStore.parseColorOr(config.colors.inputBg, "#4012131A")

            // 位置持久化：从 SharedPreferences 读取，回退到 companion 缓存
            val prefs = service.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            params.x = prefs.getInt(KEY_X, lastX)
            params.y = prefs.getInt(KEY_Y, lastY)
            lastX = params.x
            lastY = params.y

            val density = service.resources.displayMetrics.density
            fun dp(value: Float) = (value * density).toInt()

            // 1. 创建整体包裹容器 (水平排列，当贴在左侧时，菜单向右展开)
            containerView = LinearLayout(context).apply {
                orientation = LinearLayout.HORIZONTAL
                gravity = Gravity.CENTER_VERTICAL
                setOnTouchListener { _, event ->
                    if (event.action == MotionEvent.ACTION_OUTSIDE) {
                        if (isExpanded) {
                            collapse()
                        }
                    }
                    false
                }
            }

            // 2. 创建高透明度悬浮球/边缘竖线 (仅 3dp 宽的极简胶囊，搭配 24dp 的宽触控区)
            val bubbleLayout = FrameLayout(context).apply {
                layoutParams = LinearLayout.LayoutParams(dp(24f), dp(60f))
            }

            // 边缘指示竖线：accent 色取 RGB + 固定 0xB0 alpha（保持 70% 透明）
            val indicatorColor = (colorAccent and 0x00FFFFFF) or 0xB0000000.toInt()
            val indicatorView = View(context).apply {
                background = GradientDrawable().apply {
                    shape = GradientDrawable.RECTANGLE
                    cornerRadius = dp(1.5f).toFloat()
                    setColor(indicatorColor)
                }
                layoutParams = FrameLayout.LayoutParams(dp(3f), dp(44f)).apply {
                    gravity = Gravity.CENTER_VERTICAL or Gravity.START
                }
            }
            bubbleLayout.addView(indicatorView)
            bubbleView = bubbleLayout

            // 3. 创建展开菜单 (垂直布局，高紧凑度设计)
            // 菜单背景：实色 cardBg（per plan §T4）
            val menuBgColor = colorCardBg
            // 菜单描边：border 色 + 半透明 alpha
            val menuBorderColor = (colorBorder and 0x00FFFFFF) or 0x22000000.toInt()
            val menuBg = GradientDrawable().apply {
                shape = GradientDrawable.RECTANGLE
                cornerRadius = dp(10f).toFloat()
                setColor(menuBgColor)
                setStroke(dp(0.8f), menuBorderColor)
            }

            menuView = LinearLayout(context).apply {
                orientation = LinearLayout.VERTICAL
                gravity = Gravity.CENTER_HORIZONTAL
                background = menuBg
                setPadding(dp(4f), dp(4f), dp(4f), dp(4f))
                visibility = View.GONE
                layoutParams = LinearLayout.LayoutParams(
                    dp(96f),
                    LinearLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    leftMargin = dp(4f)
                }
            }

            // Vector icons
            val sizePx = dp(14f)
            val strokePx = dp(1.4f).toFloat()
            // ScanIconDrawable：accentFg 色（在 accent 底按钮上可见），laserColor 保留红色语义
            val ocrIcon = ScanIconDrawable(colorAccentFg, strokePx, 0xFFF87171.toInt(), sizePx)
            // PinIconDrawable：fgSecondary 色
            val pinIcon = PinIconDrawable(colorFgSecondary, strokePx, sizePx)

            // Button 1: 识别账单（主操作：accent 底 accentFg 字）
            // 背景常时：accent 色取 RGB + 固定 0x1F alpha（约 12%）
            val btnOcrBgNormal = (colorAccent and 0x00FFFFFF) or 0x1F000000.toInt()
            // 按下加深：accent 色取 RGB + 固定 0x40 alpha（约 25%）
            val btnOcrBgPressed = (colorAccent and 0x00FFFFFF) or 0x40000000.toInt()

            val btnOcr = TextView(context).apply {
                text = config.labels.ballOcr
                setTextColor(colorAccentFg)
                textSize = 11f
                paint.isFakeBoldText = true
                gravity = Gravity.CENTER_VERTICAL
                setPadding(dp(6f), 0, dp(6f), 0)
                background = GradientDrawable().apply {
                    cornerRadius = dp(7f).toFloat()
                    setColor(btnOcrBgNormal)
                }
                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    dp(32f)
                ).apply {
                    bottomMargin = dp(5f)
                }
                setCompoundDrawablesWithIntrinsicBounds(ocrIcon, null, null, null)
                compoundDrawablePadding = dp(4f)
                setOnTouchListener { view, event ->
                    when (event.action) {
                        MotionEvent.ACTION_DOWN -> {
                            view.background = GradientDrawable().apply {
                                cornerRadius = dp(7f).toFloat()
                                setColor(btnOcrBgPressed)
                            }
                        }
                        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                            view.background = GradientDrawable().apply {
                                cornerRadius = dp(7f).toFloat()
                                setColor(btnOcrBgNormal)
                            }
                            if (event.action == MotionEvent.ACTION_UP) {
                                view.performClick()
                            }
                        }
                    }
                    true
                }
                setOnClickListener {
                    service.triggerManualExtraction()
                }
            }

            // Button 2: 记住此页（次要操作：inputBg 底 fgPrimary 字，per plan §T4）
            // 背景常时：inputBg 色取 RGB + 固定 0x15 alpha
            val btnRememberBgNormal = (colorInputBg and 0x00FFFFFF) or 0x15000000.toInt()
            // 按下加深：inputBg 色取 RGB + 固定 0x30 alpha
            val btnRememberBgPressed = (colorInputBg and 0x00FFFFFF) or 0x30000000.toInt()

            val btnRemember = TextView(context).apply {
                text = config.labels.ballRemember
                setTextColor(colorFgPrimary)
                textSize = 11f
                paint.isFakeBoldText = true
                gravity = Gravity.CENTER_VERTICAL
                setPadding(dp(6f), 0, dp(6f), 0)
                background = GradientDrawable().apply {
                    cornerRadius = dp(7f).toFloat()
                    setColor(btnRememberBgNormal)
                }
                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    dp(32f)
                )
                setCompoundDrawablesWithIntrinsicBounds(pinIcon, null, null, null)
                compoundDrawablePadding = dp(4f)
                setOnTouchListener { view, event ->
                    when (event.action) {
                        MotionEvent.ACTION_DOWN -> {
                            view.background = GradientDrawable().apply {
                                cornerRadius = dp(7f).toFloat()
                                setColor(btnRememberBgPressed)
                            }
                        }
                        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                            view.background = GradientDrawable().apply {
                                cornerRadius = dp(7f).toFloat()
                                setColor(btnRememberBgNormal)
                            }
                            if (event.action == MotionEvent.ACTION_UP) {
                                view.performClick()
                            }
                        }
                    }
                    true
                }
                setOnClickListener {
                    try {
                        service.rememberCurrentPage()
                        FloatingTip(service, config.labels.rememberSuccess, FloatingTip.TipPosition.TOP, 2500L).show()
                    } catch (e: Exception) {
                        FloatingTip(service, "${config.labels.rememberFail}: ${e.message}", FloatingTip.TipPosition.TOP, 2500L).show()
                    }
                    collapse()
                }
            }

            menuView?.addView(btnOcr)
            menuView?.addView(btnRemember)

            containerView?.addView(bubbleView)
            containerView?.addView(menuView)

            // 4. 设置悬浮条拖动事件 (点击即展开，拖动则调整位置)
            var initialX = 0
            var initialY = 0
            var initialTouchX = 0f
            var initialTouchY = 0f
            var isMoving = false

            bubbleView?.setOnTouchListener { _, event ->
                when (event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        initialX = params.x
                        initialY = params.y
                        initialTouchX = event.rawX
                        initialTouchY = event.rawY
                        isMoving = false
                        true
                    }
                    MotionEvent.ACTION_MOVE -> {
                        val dx = (event.rawX - initialTouchX).toInt()
                        val dy = (event.rawY - initialTouchY).toInt()
                        if (Math.abs(dx) > 10 || Math.abs(dy) > 10) {
                            isMoving = true
                        }
                        params.x = initialX + dx
                        params.y = initialY + dy
                        containerView?.let { windowManager.updateViewLayout(it, params) }

                        lastX = params.x
                        lastY = params.y
                        true
                    }
                    MotionEvent.ACTION_UP -> {
                        if (!isMoving) {
                            toggleMenu()
                        } else {
                            // 拖动抬起时自动吸附到屏幕边缘（指示器中心对齐边缘）
                            if (params.x < service.resources.displayMetrics.widthPixels / 2) {
                                params.x = -dp(1.5f)
                            } else {
                                params.x = service.resources.displayMetrics.widthPixels - dp(24f) + dp(1.5f)
                            }
                            containerView?.let { windowManager.updateViewLayout(it, params) }

                            lastX = params.x
                            lastY = params.y

                            // 位置持久化：吸附后写入 SharedPreferences
                            prefs.edit()
                                .putInt(KEY_X, params.x)
                                .putInt(KEY_Y, params.y)
                                .apply()
                        }
                        true
                    }
                    else -> false
                }
            }

            windowManager.addView(containerView, params)
            Log.i(TAG, "记账助手悬浮窗显示成功")
        } catch (e: Exception) {
            Log.e(TAG, "记账助手悬浮窗创建失败: ${e.message}", e)
            // 修复：失败时清理状态，允许下次重试
            containerView = null
            bubbleView = null
            menuView = null
        }
    }

    private fun toggleMenu() {
        if (isExpanded) {
            collapse()
        } else {
            expand()
        }
    }

    private fun expand() {
        bubbleView?.visibility = View.GONE
        menuView?.visibility = View.VISIBLE
        isExpanded = true
    }

    fun collapse() {
        menuView?.visibility = View.GONE
        bubbleView?.visibility = View.VISIBLE
        isExpanded = false
    }

    fun hideTemporarily() {
        containerView?.visibility = View.GONE
    }

    fun showTemporarily() {
        containerView?.visibility = View.VISIBLE
    }

    fun dismiss() {
        try {
            containerView?.let { windowManager.removeView(it) }
        } catch (_: Exception) {}
        containerView = null
        bubbleView = null
        menuView = null
        isExpanded = false
    }
}

/**
 * 扫码/OCR 矢量图标 drawable。
 */
class ScanIconDrawable(
    private val color: Int,
    private val strokeWidthPx: Float,
    private val laserColor: Int,
    private val sizePx: Int
) : Drawable() {
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        strokeWidth = strokeWidthPx
        strokeCap = Paint.Cap.ROUND
    }

    override fun draw(canvas: Canvas) {
        val w = bounds.width().toFloat()
        val h = bounds.height().toFloat()
        paint.color = color
        paint.style = Paint.Style.STROKE

        // 绘制 4 个角的扫描框
        val len = w * 0.25f
        val pad = strokeWidthPx

        // 左上
        canvas.drawLine(pad, pad, pad + len, pad, paint)
        canvas.drawLine(pad, pad, pad, pad + len, paint)

        // 右上
        canvas.drawLine(w - pad, pad, w - pad - len, pad, paint)
        canvas.drawLine(w - pad, pad, w - pad, pad + len, paint)

        // 左下
        canvas.drawLine(pad, h - pad, pad + len, h - pad, paint)
        canvas.drawLine(pad, h - pad, pad, h - pad - len, paint)

        // 右下
        canvas.drawLine(w - pad, h - pad, w - pad - len, h - pad, paint)
        canvas.drawLine(w - pad, h - pad, w - pad, h - pad - len, paint)

        // 绘制扫描红线 (激光)
        paint.style = Paint.Style.FILL
        paint.color = laserColor
        val laserY = h / 2f
        canvas.drawRect(pad * 2f, laserY - strokeWidthPx / 2f, w - pad * 2f, laserY + strokeWidthPx / 2f, paint)
    }

    override fun getIntrinsicWidth() = sizePx
    override fun getIntrinsicHeight() = sizePx

    override fun setAlpha(alpha: Int) {}
    override fun setColorFilter(colorFilter: android.graphics.ColorFilter?) {}
    override fun getOpacity() = PixelFormat.TRANSLUCENT
}

/**
 * 图钉/记住当前页 矢量图标 drawable。
 */
class PinIconDrawable(
    private val color: Int,
    private val strokeWidthPx: Float,
    private val sizePx: Int
) : Drawable() {
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        strokeWidth = strokeWidthPx
        strokeCap = Paint.Cap.ROUND
    }

    override fun draw(canvas: Canvas) {
        val w = bounds.width().toFloat()
        val h = bounds.height().toFloat()
        paint.color = color
        val cx = w / 2f

        // 图钉头部 (帽)
        paint.style = Paint.Style.FILL
        val hatW = w * 0.35f
        val hatH = h * 0.12f
        canvas.drawRoundRect(RectF(cx - hatW, hatH, cx + hatW, hatH * 2.2f), strokeWidthPx, strokeWidthPx, paint)

        // 图钉身体 (中)
        val bodyW = w * 0.22f
        canvas.drawRect(cx - bodyW, hatH * 2.2f, cx + bodyW, h * 0.58f, paint)

        // 针尖 (底)
        paint.style = Paint.Style.STROKE
        canvas.drawLine(cx, h * 0.58f, cx, h - strokeWidthPx, paint)
    }

    override fun getIntrinsicWidth() = sizePx
    override fun getIntrinsicHeight() = sizePx

    override fun setAlpha(alpha: Int) {}
    override fun setColorFilter(colorFilter: android.graphics.ColorFilter?) {}
    override fun getOpacity() = PixelFormat.TRANSLUCENT
}
