package app.xixi.nomo

import android.app.ActivityManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.Bundle
import android.os.DeadObjectException
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.os.Message
import android.os.Messenger
import java.util.concurrent.locks.ReentrantLock

class XRayApi {
    private val lock = ReentrantLock()
    private val mReplyMsgHandler = Messenger(ReplyMsgHandler(Looper.getMainLooper()))
    private var context: Context? = null
    private var mService: Messenger? = null
    private var vpnState = VPN_STATE_IDLE
    private var xraySvrState = XRAY_SVR_IDLE
    private var isInited = false
    private var firstInit = true
    private var serviceEvent: OnXrayServiceEvent? = null
    private var vpnServiceEvent: OnVpnServiceEvent? = null

    private inner class ReplyMsgHandler(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                XRayService.XRAY_MSG_REPLY_STATUS -> {
                    val status = msg.data?.getLong("status") ?: -1L
                    val message = msg.data?.getString("message") ?: ""
                    VLog.i(TAG, "接收到VPN状态消息: status=$status, message=$message")
                    vpnServiceEvent?.onVpnStatusChange(status, message)
                    if(status == VPN_STATE_ERROR) {
                        stopXray()
                        uninit()
                    }
                }
                XRayService.XRAY_MSG_REPLY_TIMER_UPDATE -> {
                    val currentTime = msg.data?.getLong("currentTime") ?: 0L
                    val mode = msg.data?.getInt("mode") ?: 0
                    val isRunning = msg.data?.getBoolean("isRunning") ?: false
                    val isPaused = msg.data?.getBoolean("isPaused") ?: false
                    VLog.i(TAG, "接收到计时更新消息: time=$currentTime, mode=$mode, running=$isRunning, paused=$isPaused")
                    vpnServiceEvent?.onTimerUpdate(currentTime, mode, isRunning, isPaused)
                }
                XRayService.XRAY_MSG_REPLY_STOP -> {
                    VLog.i(TAG, "接收到停止消息")
                    uninit()
                }
                else -> {
                    VLog.w(TAG, "未知的消息类型: ${msg.what}")
                }
            }
        }
    }

    private fun interface OnXrayServiceEvent {
        fun onXrayServiceStarted()
    }

    interface OnVpnServiceEvent {
        fun onVpnStatusChange(status: Long, message: String)
        fun onTimerUpdate(currentTime: Long, mode: Int, isRunning: Boolean, isPaused: Boolean)
    }

    private val mConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, service: IBinder) {
            VLog.i(TAG, "xray service connected 服务连接成功")
            mService = Messenger(service)
            lock.lock()
            try {
                xraySvrState = XRAY_SVR_SERVICE_WORKING
                VLog.i(TAG, "服务状态更新为 XRAY_SVR_SERVICE_WORKING")
            } finally {
                lock.unlock()
            }
            // 如果有等待执行的事件，现在执行
            serviceEvent?.let {
                VLog.i(TAG, "执行等待的服务事件")
                it.onXrayServiceStarted()
                serviceEvent = null
            }
            regReplyMessenger();
        }

        override fun onServiceDisconnected(className: ComponentName) {
            VLog.i(TAG, "xray service disconnected 服务断开连接")
            lock.lock()
            try {
                mService = null
                vpnState = VPN_STATE_IDLE
                xraySvrState = XRAY_SVR_IDLE
                vpnServiceEvent?.onVpnStatusChange(VPN_STATE_SERVICE_DISCONNECTED, "xray service disconnected")
            } finally {
                lock.unlock()
                uninit()
            }
        }
    }

    private fun regReplyMessenger() {
        val msg = Message.obtain(null, XRayService.XRAY_MSG_REG_MESSENGER, 0, 0)
        try {
            msg.replyTo = mReplyMsgHandler
            mService?.send(msg)
            VLog.i(TAG, "注册replyTo消息已发送到 XRayService")
        } catch (e: DeadObjectException) {
            VLog.e(TAG, "发送注册replyTo消息失败：DeadObjectException", e)
        } catch (e: Exception) {
            VLog.e(TAG, "发送注册replyTo消息失败", e)
        }
    }


    fun init(context: Context) {
        VLog.i(TAG, "XRayApi init 开始")
        if (isInited) {
            VLog.i(TAG, "XRayApi 已经初始化，跳过")
            return
        }
        this.context = context
        isInited = true

        lock.lock()
        try {
            if (xraySvrState != XRAY_SVR_IDLE) {
                VLog.i(TAG, "XRay 服务状态不是 IDLE，当前状态: $xraySvrState")
                return
            }
            doStartVpnService(null)
            VLog.i(TAG, "XRayApi init 完成，开始启动和绑定服务")
        } finally {
            lock.unlock()
        }
    }

    fun uninit() {
        if (!isInited) return
        VLog.i(TAG, "uninit 开始清理服务")
        
        try {
            context?.unbindService(mConnection)
            VLog.i(TAG, "Service 已解绑")
        } catch (e: Exception) {
            VLog.e(TAG, "解绑 Service 失败", e)
        }
        
        // 重要：停止 Service（因为启动时用了 startService）
        try {
            val intent = Intent(context, XRayService::class.java)
            context?.stopService(intent)
            VLog.i(TAG, "stopService 已调用")
        } catch (e: Exception) {
            VLog.e(TAG, "停止 Service 失败", e)
        }
        
        lock.lock()
        try {
            xraySvrState = XRAY_SVR_IDLE
        } finally {
            lock.unlock()
        }
        isInited = false
        firstInit = true
        VLog.i(TAG, "uninit 完成")
    }

    private fun doStartVpnService(callback: OnXrayServiceEvent?) {
        context?.let { ctx ->
            VLog.i(TAG, "doStartVpnService 开始")
            doStartService(ctx)
            val intent = Intent(ctx, XRayService::class.java)
            VLog.i(TAG, "准备绑定 xray service")
            if (!ctx.bindService(intent, mConnection, 0)) {
                VLog.e(TAG, "绑定 xray service 失败")
                return
            }
            xraySvrState = XRAY_SVR_CONNECT_SERVICE
            serviceEvent = callback
            VLog.i(TAG, "xray service 绑定请求已发送，状态更新为 XRAY_SVR_CONNECT_SERVICE")
        }
    }

    private fun doStartService(context: Context) {
        if (isServiceRunning(context)) {
            VLog.i(TAG, "XRayService 已经在运行")
            return
        }
        val intent = Intent(context, XRayService::class.java)
        VLog.i(TAG, "启动 XRayService")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        } else {
            context.startService(intent)
        }
        VLog.i(TAG, "XRayService 启动命令已发送")
    }

    fun startXray(config: XrayConfig): Boolean {
        lock.lock()
        return try {
            VLog.i(TAG, "startXray 开始，当前 xraySvrState = $xraySvrState")
            when (xraySvrState) {
                XRAY_SVR_IDLE -> {
                    VLog.w(TAG, "服务状态为 IDLE，需要先启动服务")
                    doStartVpnService(OnXrayServiceEvent {
                        VLog.i(TAG, "服务启动完成，开始 startXray")
                        doStartXray(config)
                    })
                    lock.unlock()
                    true
                }
                XRAY_SVR_CONNECT_SERVICE, XRAY_SVR_QUERY_STATE -> {
                    VLog.i(TAG, "服务正在连接中，注册回调等待连接完成")
                    serviceEvent = OnXrayServiceEvent {
                        VLog.i(TAG, "服务连接完成，现在执行 startXray")
                        doStartXray(config)
                    }
                    lock.unlock()
                    true
                }
                XRAY_SVR_SERVICE_WORKING -> {
                    lock.unlock()
                    VLog.i(TAG, "服务已就绪，直接启动 xray")
                    doStartXray(config)
                }
                else -> {
                    VLog.e(TAG, "未知的服务状态: $xraySvrState")
                    lock.unlock()
                    false
                }
            }
        } catch (e: Exception) {
            VLog.e(TAG, "startXray 异常", e)
            lock.unlock()
            false
        }
    }

    fun doStartXray(config: XrayConfig): Boolean {
        VLog.i(TAG, "doStartXray 开始执行")
        VLog.i(TAG, "配置信息 - socksPort: ${config.socksPort}, sessionId: ${config.sessionId}")
        
        val msg = Message.obtain(null, XRayService.XRAY_MSG_START, 0, 0)
        val bundle = Bundle().apply {
            putInt("socksPort", config.socksPort)
            putString("sessionId", config.sessionId)
            putString("tunnelConfig", config.tunnelConfig)
            putString("startOptions", config.getProxyStartOptions())
            putStringArrayList("allowVpnApps", config.allowVpnApps)
            putStringArrayList("disallowVpnApps", config.disallowVpnApps)
        }
        msg.data = bundle
        return try {
            msg.replyTo = mReplyMsgHandler
            mService?.send(msg)
            VLog.i(TAG, "启动消息已发送到 XRayService")
            true
        } catch (e: DeadObjectException) {
            VLog.e(TAG, "发送启动消息失败：DeadObjectException", e)
            false
        } catch (e: Exception) {
            VLog.e(TAG, "发送启动消息失败", e)
            false
        }
    }

    fun stopXray() {
        VLog.i(TAG, "stopXray 被调用")
        lock.lock()
        try {
            if (xraySvrState != XRAY_SVR_SERVICE_WORKING) {
                // 服务未启动，点击了关闭
                vpnServiceEvent?.onVpnStatusChange(VPN_STATE_IDLE, "")
                VLog.w(TAG, "xray 服务未在运行，当前状态: $xraySvrState")
                return
            }
        } finally {
            lock.unlock()
        }
        val msg = Message.obtain(null, XRayService.XRAY_MSG_STOP, 0, 0)
        try {
            mService?.send(msg)
            VLog.i(TAG, "停止消息已发送到 XRayService")
        } catch (e: Exception) {
            VLog.e(TAG, "发送停止消息失败", e)
        }
    }

    fun setVpnServiceEventListener(listener: OnVpnServiceEvent?) {
        vpnServiceEvent = listener
    }

    companion object {
        private const val TAG = "ixvpn"
        const val XRAY_SVR_IDLE = 0
        const val XRAY_SVR_CONNECT_SERVICE = 1
        const val XRAY_SVR_QUERY_STATE = 2
        const val XRAY_SVR_SERVICE_WORKING = 7

        const val VPN_STATE_IDLE = 0L
        const val VPN_STATE_CONNECTING = 1L
        const val VPN_STATE_CONNECTED = 2L
        const val VPN_STATE_ERROR = 3L
        const val VPN_STATE_SERVICE_DISCONNECTED = 1000L
        const val VPN_STATE_PERMISSION_DENIED = 1001L



        fun isServiceRunning(mContext: Context): Boolean {
            val activityManager = mContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val serviceList = activityManager.getRunningServices(300)

            if (serviceList.isEmpty()) {
                return false
            }

            return serviceList.any { it.service.className == "app.xixi.nomo.XRayService" }
        }
    }
}
