package app.xixi.nomo

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
import android.net.VpnService
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.os.Messenger
import android.os.ParcelFileDescriptor
import androidx.core.app.NotificationCompat
import go.Seq
import ixvpn_mobile.Ixvpn_mobile
import ixvpn_mobile.ProxyConnectorHandler


class XRayService : VpnService() {

    private val mMessenger = Messenger(IncomingHandler())
    private val tunnelService = TProxyService()
    private var tunFileDescriptor: ParcelFileDescriptor? = null

    private val vpnHandler = object : ProxyConnectorHandler {
        override fun proxyStatusChange(l: Long, msg: String) {
            VLog.i(TAG, "status:$l msg:$msg")
            // 发送状态消息到XRayApi
            sendStatusMessage(l, msg)
        }
    }

    private inner class IncomingHandler : Handler() {
        override fun handleMessage(msg: Message) {
            handleRemoteMessage(msg)
        }
    }

    override fun onBind(intent: Intent): IBinder? {
        // 首先检查是否是 VPN 服务的绑定请求
        if (SERVICE_INTERFACE == intent.action) {
            return super.onBind(intent)
        }
        // 其他绑定请求返回 Messenger
        return mMessenger.binder
    }

    override fun onCreate() {
        super.onCreate()
        // 初始化文件日志系统
        VLog.init(applicationContext)
        VLog.i(TAG, "XRayService onCreate")
        
        Seq.setContext(applicationContext)
        Ixvpn_mobile.initProxyConnector()
        createNotificationChannel()
    }

    override fun onRevoke() {
        super.onRevoke()
        VLog.i(TAG, "onRevoke")
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        VLog.i(TAG, "onTaskRemoved")
    }

    override fun onDestroy() {
        VLog.i(TAG, "onDestroy")
        // 先停止前台服务
        try {
            stopForeground(STOP_FOREGROUND_REMOVE)
        } catch (e: Exception) {
            VLog.e(TAG, "stopForeground 失败", e)
        }
        
        // 清理资源
        try {
            Ixvpn_mobile.freeProxyConnector()
        } catch (e: Exception) {
            VLog.e(TAG, "freeProxyConnector 失败", e)
        }
        
        // 关闭日志系统
        VLog.close()
        
        super.onDestroy()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        createNotification()
        return START_NOT_STICKY
    }

    private fun handleRemoteMessage(msg: Message) {
        when (msg.what) {
            XRAY_MSG_START -> dealStartMsg(msg)
            XRAY_MSG_STOP -> dealStopMsg()
        }
    }

    private fun dealStartMsg(msg: Message) {
        VLog.i(TAG, "deal start xray msg")
        val bundle = msg.data
        val socksPort = bundle.getInt("socksPort")
        val startOptions = bundle.getString("startOptions")
        val sessionId = bundle.getString("sessionId")
        val allowVpnApps = bundle.getStringArrayList("allowVpnApps") ?: arrayListOf()
        val disallowVpnApps = bundle.getStringArrayList("disallowVpnApps") ?: arrayListOf()
        
        VLog.i(TAG, "socksPort: $socksPort, sessionId: $sessionId")
        VLog.i(TAG, "allowVpnApps count: ${allowVpnApps.size}, disallowVpnApps count: ${disallowVpnApps.size}")
        
        try {
            val builder = Builder()
            val ipAddress = "192.168.34.2"
            builder.setSession("ixvpn")
                .setMtu(1500)
                .addAddress(ipAddress, 24)
                .addRoute("0.0.0.0", 0)
                .addDnsServer("8.8.8.8")

            if (allowVpnApps.isNotEmpty()) {
                allowVpnApps.forEach { app ->
                    builder.addAllowedApplication(app)
                }
                VLog.i(TAG, "允许的应用: ${allowVpnApps.joinToString(", ")}")
            } else {
                disallowVpnApps.forEach { app ->
                    builder.addDisallowedApplication(app)
                }
                builder.addDisallowedApplication(packageName)
                VLog.i(TAG, "禁止的应用: ${disallowVpnApps.joinToString(", ")}")
            }
            
            tunFileDescriptor = builder.establish()
            tunFileDescriptor?.let { tfd ->
                VLog.i(TAG, "VPN tunnel established, fd: ${tfd.fd}")
                tunnelService.startTunnel(this, socksPort, tfd.fd)
                Ixvpn_mobile.proxyConnectorStart(sessionId, startOptions, vpnHandler)
                VLog.i(TAG, "XRay proxy started successfully")
            } ?: run {
                VLog.e(TAG, "Failed to establish VPN tunnel")
            }
        } catch (e: Exception) {
            VLog.e(TAG, "启动 XRay 失败", e)
        }
    }

    private fun dealStopMsg() {
        VLog.i(TAG, "deal stop xray msg")
        doStop()
    }

    private fun doStop() {
        VLog.i(TAG, "开始停止 XRay 服务")
        try {
            tunnelService.stopTunnel()
            VLog.i(TAG, "Tunnel stopped")
        } catch (e: Exception) {
            VLog.e(TAG, "停止 tunnel 失败", e)
        }
        
        try {
            Ixvpn_mobile.proxyConnectorStop()
            VLog.i(TAG, "Proxy connector stopped")
        } catch (e: Exception) {
            VLog.e(TAG, "停止 proxy connector 失败", e)
        }
        
        tunFileDescriptor?.let { tfd ->
            try {
                tfd.close()
                VLog.i(TAG, "TUN file descriptor closed")
            } catch (e: Exception) {
                VLog.e(TAG, "关闭 TUN file descriptor 失败", e)
            }
            tunFileDescriptor = null
        }
        VLog.i(TAG, "xray stopped")
    }

    private fun sendStatusMessage(status: Long, message: String) {
        try {
            val intent = Intent("xray_service_stat_message").apply {
                putExtra("status", status)
                putExtra("message", message)
            }
            sendBroadcast(intent)
            VLog.i(TAG, "状态消息已发送: status=$status, message=$message")
        } catch (e: Exception) {
            VLog.e(TAG, "发送状态消息失败", e)
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelName = "NoMo Service Notifications"
            val channelDescription = "NoMo Service is running in the background"
            val importance = NotificationManager.IMPORTANCE_LOW

            val channel = NotificationChannel(CHANNEL_ID, channelName, importance)
            channel.setShowBadge(false)
            channel.description = channelDescription

            val notificationManager =
                getSystemService(NotificationManager::class.java)
            notificationManager?.createNotificationChannel(channel)
        }
    }

    private fun createNotification() {
        VLog.i(TAG, "开始创建通知")
        try {
            val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("NoMo Service Running")
                //.setContentText("NoMo connection is active.")
                .setSmallIcon(R.drawable.ic_xvpn)
                .setPriority(NotificationCompat.PRIORITY_MIN)
                .setOngoing(true)
                .setShowWhen(false)
                .setOnlyAlertOnce(true)
                .build()

            VLog.i(TAG, "通知创建成功，准备启动前台服务")
            
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                try {
                    startForeground(1, notification, FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED)
                    VLog.i(TAG, "前台服务已启动 (Android 14+)")
                } catch (e: SecurityException) {
                    VLog.w(TAG, "使用 SYSTEM_EXEMPTED 类型失败，降级为普通前台服务", e)
                    startForeground(1, notification)
                    VLog.i(TAG, "前台服务已启动 (降级模式)")
                }
            } else {
                startForeground(1, notification)
                VLog.i(TAG, "前台服务已启动")
            }
        } catch (e: Exception) {
            VLog.e(TAG, "创建通知失败", e)
        }
    }

    companion object {
        const val XRAY_MSG_START = 1
        const val XRAY_MSG_STOP = 2
        private const val TAG = "ixvpn"

        private const val CHANNEL_ID: String = "nomo_channel_id"
    }
}
