package app.xixi.nomo

import CoreApi
import FlutterError
import OnEventChangeStreamHandler
import PigeonEventSink
import android.app.Activity
import android.content.Context.TELEPHONY_SERVICE
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
import android.net.VpnService
import android.telephony.TelephonyManager
import android.util.Base64
import android.util.Log
import app.xixi.nomo.XRayApi.Companion.VPN_STATE_PERMISSION_DENIED
import app.xixi.nomo.XRayApi.OnVpnServiceEvent
import com.google.gson.Gson
import io.flutter.plugin.common.BinaryMessenger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.InputStream
import androidx.core.graphics.createBitmap
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.google.gson.JsonSyntaxException
import java.util.Locale

// 消息数据类
data class VpnStatusMessage(
    val type: String,
    val status: Long,
    val message: String
)

data class TimerUpdateMessage(
    val type: String,
    val currentTime: Long,
    val mode: Int,
    val isRunning: Boolean,
    val isPaused: Boolean
)

class CoreApiImpl(private val activity: Activity) : CoreApi {
    companion object {
        private const val TAG = "CoreApiImpl"
        private const val REQUEST_VPN_PERMISSION = 1001
    }
    
    // 事件流处理器
    private var eventSink: PigeonEventSink<String>? = null

    // xray服务
    private var xrayApi: XRayApi? = null

    private var sessionId: String = ""
    private var socksPort: Long = 10808
    private var tunnelConfig: String = ""
    private var configJson: String = ""

    
    // 事件流处理器实现
    private val eventStreamHandler = object : OnEventChangeStreamHandler() {
        override fun onListen(p0: Any?, sink: PigeonEventSink<String>) {
            Log.d(TAG, "Flutter 开始监听事件变化")
            eventSink = sink
        }
        
        override fun onCancel(p0: Any?) {
            Log.d(TAG, "Flutter 取消监听事件变化")
            eventSink = null
        }
    }
    
    // 注册事件流处理器
    fun registerEventStreamHandler(messenger: BinaryMessenger) {
        OnEventChangeStreamHandler.register(messenger, eventStreamHandler)
        Log.d(TAG, "事件流处理器已注册")
    }

    // 通知 Flutter VPN状态变化
    private fun notifyVpnStatusChange(status: Long, message: String) {
        val vpnMessage = VpnStatusMessage(
            type = "vpn_status",
            status = status,
            message = message
        )
        notifyFlutter(vpnMessage)
    }
    
    // 通知 Flutter 计时更新
    private fun notifyTimerUpdate(currentTime: Long, mode: Int, isRunning: Boolean, isPaused: Boolean) {
        val timerMessage = TimerUpdateMessage(
            type = "timer_update",
            currentTime = currentTime,
            mode = mode,
            isRunning = isRunning,
            isPaused = isPaused
        )
        notifyFlutter(timerMessage)
    }

    // 通用通知方法
    private fun notifyFlutter(message: Any) {
        eventSink?.let { sink ->
            try {
                val json = Gson().toJson(message)
                sink.success(json)
                Log.d(TAG, "已通知 Flutter: $json")
            } catch (e: Exception) {
                Log.e(TAG, "通知 Flutter 失败", e)
            }
        } ?: Log.w(TAG, "事件流未连接，无法通知 Flutter")
    }

    /**
     * 初始化xray服务
     */
    fun initXrayApi() {
        VLog.i(TAG, "CoreApiImpl.initXrayApi() 创建 XRayApi 实例")
        xrayApi = XRayApi()
    }

    /**
     * 设置XRayApi状态监听
     */
    fun setVpnServiceEventListener() {
        xrayApi?.setVpnServiceEventListener(object : OnVpnServiceEvent {
            override fun onVpnStatusChange(status: Long, message: String) {
                VLog.i(TAG, "接收到VPN状态变化: status=$status, message=$message")
                // 同时发送详细的状态信息
                notifyVpnStatusChange(status, message)
            }
            
            override fun onTimerUpdate(currentTime: Long, mode: Int, isRunning: Boolean, isPaused: Boolean) {
                VLog.i(TAG, "接收到计时更新: time=$currentTime, mode=$mode, running=$isRunning, paused=$isPaused")
                notifyTimerUpdate(currentTime, mode, isRunning, isPaused)
            }
        })
    }

    fun xrayInit() {
        VLog.i(TAG, "CoreApiImpl.xrayInit() 被调用")
        xrayApi?.init(activity)
        VLog.i(TAG, "CoreApiImpl.xrayInit() 调用完成")
    }

    fun xrayUnInit() {
        xrayApi?.uninit()
    }

    override fun getSystemLocale(): String? {
        val locale: Locale = activity.resources.configuration.locales[0]
        return locale.language
    }

    override fun getApps(callback: (Result<String?>) -> Unit) {
        val apps = ArrayList<HashMap<String, Any>>()
        val pm: PackageManager = activity.packageManager

        // 通过隐式 Intent，查询所有支持 ACTION_MAIN 的应用
        val intent = Intent(Intent.ACTION_MAIN).apply {
            addCategory(Intent.CATEGORY_LAUNCHER) // 查询所有可以启动的应用
        }
        val launcherApps = pm.queryIntentActivities(intent, 0)
        // 使用协程处理所有游戏应用信息
        CoroutineScope(Dispatchers.Default).launch {
            for (app in launcherApps) {
                val appInfo = getAppInfo(app.activityInfo.applicationInfo, pm)
                if ((app.activityInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) == 0) {
                    apps.add(0, appInfo)
                } else {
                    apps.add(appInfo) 
                }
            }
            withContext(Dispatchers.Main) {
                callback(Result.success(Gson().toJson(apps)))
            }
        }
    }

    // 获取应用的详细信息
    private suspend fun getAppInfo(
        app: ApplicationInfo,
        pm: PackageManager,
    ): HashMap<String, Any> = withContext(Dispatchers.IO) {
        val appInfo = HashMap<String, Any>()
        try {
            appInfo["packageName"] = app.packageName
            appInfo["appName"] = pm.getApplicationLabel(app).toString()
            try {
                val drawable = app.loadIcon(pm)
                val bitmap = drawable2Bitmap(drawable)
                val bytes = bitmap2Bytes(bitmap)
                bitmap.recycle()
                appInfo["icon"] = Base64.encodeToString(bytes, Base64.NO_WRAP)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        appInfo
    }

    // Drawable转换成Bitmap
    private fun drawable2Bitmap(drawable: Drawable): Bitmap {
        val width = drawable.intrinsicWidth.coerceAtMost(128) // 限制最大宽度
        val height = drawable.intrinsicHeight.coerceAtMost(128) // 限制最大高度
        val bitmap = createBitmap(
            width,
            height,
            if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
        )
        val canvas = Canvas(bitmap)
        drawable.setBounds(0, 0, width, height)
        drawable.draw(canvas)
        return bitmap
    }

    // Bitmap转换成byte[]
    private fun bitmap2Bytes(bm: Bitmap): ByteArray {
        val bos = ByteArrayOutputStream()
        bm.compress(Bitmap.CompressFormat.PNG, 100, bos)
        return bos.toByteArray()
    }

    override fun connect(sessionId: String, socksPort: Long, tunnelConfig: String, configJson: String): Boolean? {
        this.sessionId = sessionId
        this.socksPort = socksPort
        this.tunnelConfig = tunnelConfig
        this.configJson = configJson
        Log.i(TAG, "Starting V2Ray with permission check")
        // 检查VPN权限
        val intent = VpnService.prepare(activity)
        if (intent == null) {
            // 已有VPN权限，直接启动
            Log.i(TAG, "VPN permission already granted")
            startV2RayService()
        } else {
            // 需要请求VPN权限
            Log.i(TAG, "Requesting VPN permission")
            activity.startActivityForResult(intent, REQUEST_VPN_PERMISSION)
        }
        return true
    }

    override fun disconnect(): Boolean? {
        VLog.i(TAG, "============ 开始停止 V2Ray 服务 ============")
        
        // 停止V2Ray服务
        VLog.i(TAG, "调用 xrayApi.stopXray()")
        xrayApi?.stopXray()
        xrayUnInit()
        VLog.i(TAG, "V2Ray 服务停止完成")

        return true
    }

    override fun getRemoteIp(): String? {
        return ""
    }

    override fun getAdvertisingId(): String? {
        return ""
    }

    override fun moveTaskToBack(): Boolean? {
        try {
            activity.moveTaskToBack(true)
            return true
        } catch (e: Exception) {
            throw FlutterError("-1", e.message)
        }
    }

    override fun getChannel(): String? {
        try {
            val pm: PackageManager = activity.packageManager
            val appInfo = pm.getApplicationInfo(activity.packageName, PackageManager.GET_META_DATA)
            val channel = appInfo.metaData?.getString("channel")!!
            return channel
        } catch (e: Exception) {
            throw FlutterError("-1", e.message)
        }
    }

    override fun isConnected(): Boolean? {
        val isRunning = XRayApi.isServiceRunning(activity)
        VLog.i(TAG, "XRayService is running = $isRunning")
        return isRunning
    }

    override fun getSimInfo(): String? {
        try {
            val telephonyManager = activity.getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            val simState = telephonyManager.simState
            val simReady = simState == TelephonyManager.SIM_STATE_READY

            val carrierName = telephonyManager.simOperatorName ?: "Unknown"
            val simOperator = telephonyManager.simOperator ?: ""
            val simCountryIso = telephonyManager.simCountryIso ?: ""
            val mcc = if (simOperator.length >= 3) simOperator.substring(0, 3) else ""
            val mnc = if (simOperator.length > 3) simOperator.substring(3) else ""

            val networkCarrierName = telephonyManager.networkOperatorName ?: "Unknown"
            val networkOperator = telephonyManager.networkOperator ?: ""
            val networkCountryIso = telephonyManager.networkCountryIso ?: ""
            val networkMcc =
                if (networkOperator.length >= 3) networkOperator.substring(0, 3) else ""
            val networkMnc = if (networkOperator.length > 3) networkOperator.substring(3) else ""

            val data = mapOf(
                "simReady" to simReady,
                "carrierName" to carrierName,
                "mcc" to mcc,
                "mnc" to mnc,
                "countryIso" to simCountryIso,
                "networkCarrierName" to networkCarrierName,
                "networkMcc" to networkMcc,
                "networkMnc" to networkMnc,
                "networkCountryIso" to networkCountryIso
            )
            return Gson().toJson(data)
        } catch (e: Exception) {
            throw FlutterError("-1", e.message)
        }
    }

    override fun reconnect(): Boolean? {
        xrayInit()
        return true
    }

    fun startV2RayService() {
        VLog.i(TAG, "============ 开始启动 V2Ray 服务 ============")
        
        // 1. 初始化 XRay (启动和绑定服务)
        VLog.i(TAG, "步骤 1: 调用 xrayInit() 初始化服务")
        xrayInit()
        
        // 2. 启动 XRay (发送启动消息)
        // 注意：startXray() 内部已经处理了等待服务连接的逻辑
        // 如果服务还在连接中 (XRAY_SVR_CONNECT_SERVICE)，会注册回调等待
        // 如果服务已连接 (XRAY_SVR_SERVICE_WORKING)，会直接发送启动消息
        VLog.i(TAG, "步骤 2: 调用 startXray() 启动代理")
        startXray()
        
        VLog.i(TAG, "startV2RayService 调用完成，等待服务连接和启动")
        // 注意：实际的连接成功应该在服务启动完成后通知
    }

    // 启动V2Ray服务
    private fun startXray() {
        VLog.i(TAG, "CoreApiImpl.startXray() 被调用，开始准备配置")
        
        val config = XrayConfig()
        config.sessionId = sessionId
        config.socksPort = socksPort.toInt()
        config.tunnelConfig = tunnelConfig
        
        VLog.i(TAG, "sessionId: ${config.sessionId}")
        VLog.i(TAG, "socksPort: ${config.socksPort}")
        VLog.i(TAG, "tunnelConfig: ${config.tunnelConfig}")
        
        val detectOptions = StatusDetectOptions()
        detectOptions.statusDetectInterval = 60
        val detectUrls = ArrayList<String>()
        detectUrls.add("https://www.baidu.com")
        detectOptions.statusDetectUrls = detectUrls
        val jsonArray = safeStringToJsonArray(configJson)
        val proxyNodes= ArrayList<ProxyNode>()
        jsonArray?.forEach {
            if(it.isJsonObject) {
                val obj: JsonObject = it.asJsonObject
                val nodeId = obj.get("nodeId").asString
                val coreConfig = obj.get("coreConfig").asString
                VLog.i(TAG, "coreConfig: $coreConfig")
                val proxyNode = ProxyNode()
                proxyNode.nodeId = nodeId
//                VLog.i(TAG, "读取配置文件: connect.json")
//                proxyNode.coreConfig = readAssets("connect.json")
                proxyNode.coreConfig = coreConfig
                proxyNodes.add(proxyNode)
            }
        }

        val startOptions = ProxyStartOptions()
        startOptions.socksPort = config.socksPort
        startOptions.nodes = proxyNodes
        startOptions.statusDetectOptions = detectOptions
        config.startOptions = startOptions
        
        VLog.i(TAG, "配置准备完成，调用 xrayApi.startXray()")
        val result = xrayApi?.startXray(config)
        VLog.i(TAG, "xrayApi.startXray() 返回结果: $result")
    }

    fun safeStringToJsonArray(jsonString: String?): JsonArray? {
        if (jsonString.isNullOrBlank()) return null

        return try {
            val element: JsonElement = JsonParser.parseString(jsonString)
            if (element.isJsonArray) element.asJsonArray else null
        } catch (e: JsonSyntaxException) {
            e.printStackTrace()
            null
        }
    }


    private fun readAssets(fileName: String): String {
        try {
            val `in`: InputStream = activity.resources.assets.open(fileName)
            val lenght = `in`.available()
            val buffer = ByteArray(lenght)
            `in`.read(buffer)
            return String(buffer, charset("utf-8"))
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            return ""
        }
    }

    /**
     * 处理Activity结果（需要在Activity的onActivityResult中调用）
     */
    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == REQUEST_VPN_PERMISSION) {
            if (resultCode == Activity.RESULT_OK) {
                Log.i(TAG, "VPN permission granted, starting V2Ray service")
                startV2RayService()
            } else {
                Log.w(TAG, "VPN permission denied")
                notifyVpnStatusChange(VPN_STATE_PERMISSION_DENIED, "")
            }
        }
    }
}