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.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 android.os.ParcelFileDescriptor
import androidx.core.app.NotificationCompat
import app.xixi.nomo.XRayApi.Companion.VPN_STATE_CONNECTED
import app.xixi.nomo.XRayApi.Companion.VPN_STATE_ERROR
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 var replyMessenger: Messenger? = null

    // 计时功能相关变量
    private val timerHandler = Handler(Looper.getMainLooper())
    private var isTimerRunning = false
    private var isTimerPaused = false
    private var currentTimerTime = 0L
    private var timerStartTime = 0L
    private var timerMode = 0 // 0: 普通计时, 1: 倒计时
    
    // 计时器Runnable
    private val timerRunnable = object : Runnable {
        override fun run() {
            if (isTimerRunning && !isTimerPaused) {
                val newTime = if (timerMode == 0) {
                    // 普通计时：递增
                    currentTimerTime + 1000L
                } else {
                    // 倒计时：递减
                    currentTimerTime - 1000L
                }
                
                currentTimerTime = newTime
                
                // 检查倒计时是否结束
                if (timerMode == 1 && newTime <= 0) {
                    VLog.i(TAG, "倒计时结束 - 关闭VPN")
                    dealStopMsg()
                    notifyStop()
                    return
                }
                
                // 更新通知
                updateNotification()
                
                // 发送计时更新
                sendTimerUpdate()
                
                // 继续下一秒
                timerHandler.postDelayed(this, 1000L)
            }
        }
    }

    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")
        // 停止计时
        stopTimer()
        // 先停止前台服务
        try {
            stopForeground(STOP_FOREGROUND_REMOVE)
        } catch (e: Exception) {
            VLog.e(TAG, "stopForeground 失败", e)
        }
        
        // 清理Messenger引用
        replyMessenger = null
        VLog.i(TAG, "replyMessenger 已清理")
        
        // 清理资源
        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) {
        // 只在有replyTo时才记录Messenger对象
        if (msg.replyTo != null) {
            replyMessenger = msg.replyTo
            VLog.i(TAG, "记录replyTo Messenger: $replyMessenger")
        } else {
            VLog.w(TAG, "消息没有replyTo，无法记录Messenger")
        }
        
        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 tunnelConfig = bundle.getString("tunnelConfig")
        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, tunnelConfig, 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)
            dealStopMsg()
            stopSelf()
        }
    }

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

    private fun doStop() {
        VLog.i(TAG, "开始停止 XRay 服务")
        
        // 停止计时
        stopTimer()
        
        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 notifyStop() {
        replyMessenger?.let { messenger ->
            try {
                val msg = Message.obtain().apply {
                    what = XRAY_MSG_REPLY_STOP
                }
                messenger.send(msg)
                VLog.i(TAG, "停止消息已通过Messenger发送")
            } catch (e: DeadObjectException) {
                VLog.w(TAG, "Messenger已失效，清理引用", e)
                replyMessenger = null
            } catch (e: Exception) {
                VLog.e(TAG, "发送Messenger停止消息失败", e)
            }
        } ?: run {
            VLog.w(TAG, "replyMessenger为空，无法发送停止消息")
        }
    }

    private fun sendStatusMessage(status: Long, message: String) {
        try {
            if(status == VPN_STATE_CONNECTED) {
                // 启动计时（普通计时模式）
                startTimer(0, 0)
//                startTimer(1, 10000L)
            }
            else if(status == VPN_STATE_ERROR) {
                VLog.i(TAG, "VPN 连接失败，status：$status")
            }
            replyMessenger?.let { messenger ->
                try {
                    val msg = Message.obtain().apply {
                        what = XRAY_MSG_REPLY_STATUS
                        // 使用Bundle传递消息，避免跨进程序列化问题
                        data = Bundle().apply {
                            putLong("status", status)
                            putString("message", message)
                        }
                    }
                    messenger.send(msg)
                    VLog.i(TAG, "状态消息已通过Messenger发送: status=$status, message=$message")
                } catch (e: DeadObjectException) {
                    VLog.w(TAG, "Messenger已失效，清理引用", e)
                    replyMessenger = null
                } catch (e: Exception) {
                    VLog.e(TAG, "发送Messenger状态消息失败", e)
                }
            } ?: run {
                VLog.w(TAG, "replyMessenger为空，无法发送状态消息")
            }
        } catch (e: Exception) {
            VLog.e(TAG, "发送状态消息失败", e)
        }
    }
    
    // 计时相关方法
    private fun startTimer(mode: Int, initialTime: Long) {
        if(isTimerRunning)
            return
        VLog.i(TAG, "启动计时: mode=$mode, initialTime=$initialTime")
        timerMode = mode
        currentTimerTime = initialTime
        timerStartTime = System.currentTimeMillis()

        isTimerRunning = true
        isTimerPaused = false
        
        // 开始计时循环
        timerHandler.post(timerRunnable)
    }
    
    private fun stopTimer() {
        if(!isTimerRunning)
            return
        VLog.i(TAG, "停止计时")
        isTimerRunning = false
        isTimerPaused = false
        timerHandler.removeCallbacks(timerRunnable)
    }
    
    private fun pauseTimer() {
        if (isTimerRunning) {
            VLog.i(TAG, "暂停计时")
            isTimerPaused = true
            timerHandler.removeCallbacks(timerRunnable)
        }
    }
    
    private fun resumeTimer() {
        if (isTimerRunning && isTimerPaused) {
            VLog.i(TAG, "恢复计时")
            isTimerPaused = false
            timerHandler.post(timerRunnable)
        }
    }
    
    private fun sendTimerUpdate() {
        try {
            replyMessenger?.let { messenger ->
                try {
                    val msg = Message.obtain().apply {
                        what = XRAY_MSG_REPLY_TIMER_UPDATE
                        data = Bundle().apply {
                            putLong("currentTime", currentTimerTime)
                            putInt("mode", timerMode)
                            putBoolean("isRunning", isTimerRunning)
                            putBoolean("isPaused", isTimerPaused)
                        }
                    }
                    messenger.send(msg)
                    VLog.i(TAG, "计时更新消息已发送: time=$currentTimerTime, mode=$timerMode")
                } catch (e: DeadObjectException) {
                    VLog.w(TAG, "Messenger已失效，清理引用", e)
                    replyMessenger = null
                } catch (e: Exception) {
                    VLog.e(TAG, "发送计时更新消息失败", e)
                }
            } ?: run {
                VLog.w(TAG, "replyMessenger为空，无法发送计时更新")
            }
        } catch (e: Exception) {
            VLog.e(TAG, "发送计时更新失败", e)
        }
    }
    
    private fun updateNotification() {
        val timeText = formatTime(currentTimerTime)
        val modeText = if (timerMode == 0) "计时中" else "倒计时"
        val statusText = if (isTimerPaused) "已暂停" else "运行中"
        
        val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("NoMo Service $modeText")
            .setContentText("$timeText - $statusText")
            .setSmallIcon(R.drawable.ic_xvpn)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setOngoing(true)
            .setShowWhen(false)
            .setOnlyAlertOnce(true)
            .build()
        
        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager?.notify(1, notification)
    }
    
    private fun formatTime(timeMs: Long): String {
        val totalSeconds = Math.abs(timeMs) / 1000
        val days = totalSeconds / 86400 // 86400 = 24 * 3600
        val hours = (totalSeconds % 86400) / 3600
        val minutes = (totalSeconds % 3600) / 60
        val seconds = totalSeconds % 60
        
        return if (days > 0) {
            String.format("%d 天 %02d:%02d:%02d", days, hours, minutes, seconds)
        } else if (hours > 0) {
            String.format("%02d:%02d:%02d", hours, minutes, seconds)
        } else {
            String.format("00:%02d:%02d", minutes, seconds)
        }
    }

    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
        const val XRAY_MSG_REG_MESSENGER = 3
        const val XRAY_MSG_REPLY_STATUS = 101
        const val XRAY_MSG_REPLY_TIMER_UPDATE = 102
        const val XRAY_MSG_REPLY_STOP = 103
        private const val TAG = "ixvpn"

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