package com.dphms.netguard

import android.content.ComponentName
import android.content.Context
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.IBinder
import rikka.shizuku.Shizuku

object ShizukuManager {

    private const val SHIZUKU_PKG = "moe.shizuku.privileged.api"
    private const val PERMISSION_REQUEST_CODE = 2001

    private var activeService: INetGuardService? = null
    private var activeConnection: ServiceConnection? = null

    fun isShizukuInstalled(context: Context): Boolean {
        return try {
            context.packageManager.getPackageInfo(SHIZUKU_PKG, 0)
            true
        } catch (e: PackageManager.NameNotFoundException) {
            false
        }
    }

    fun isShizukuRunning(): Boolean {
        return try { Shizuku.pingBinder() } catch (e: Exception) { false }
    }

    fun hasPermission(): Boolean {
        return if (isShizukuRunning()) {
            try { Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED }
            catch (e: Exception) { false }
        } else false
    }

    fun requestPermission() {
        if (isShizukuRunning()) {
            try { Shizuku.requestPermission(PERMISSION_REQUEST_CODE) } catch (e: Exception) {}
        }
    }

    fun getService(): INetGuardService? = activeService

    fun bindService(context: Context, onBound: (INetGuardService?) -> Unit) {
        // Return cached service if available
        val cached = activeService
        if (cached != null) {
            try {
                cached.listAllPackages() // health check
                onBound(cached)
                return
            } catch (e: Exception) {
                activeService = null
                activeConnection = null
            }
        }

        if (!isShizukuRunning() || !hasPermission()) {
            onBound(null)
            return
        }

        val args = Shizuku.UserServiceArgs(
            ComponentName(context, NetGuardServiceImpl::class.java)
        ).processNameSuffix("netguard")
            .debuggable(false)
            .version(1)

        val connection = object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                if (service != null) {
                    val proxy = INetGuardService.Stub.asInterface(service)
                    activeService = proxy
                    activeConnection = this
                    onBound(proxy)
                } else {
                    onBound(null)
                }
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                activeService = null
                activeConnection = null
            }
        }

        try {
            Shizuku.bindUserService(args, connection)
            activeConnection = connection
        } catch (e: Exception) {
            onBound(null)
        }
    }

    fun unbindService(context: Context) {
        val conn = activeConnection
        if (conn != null) {
            try {
                val args = Shizuku.UserServiceArgs(
                    ComponentName(context, NetGuardServiceImpl::class.java)
                ).processNameSuffix("netguard").debuggable(false).version(1)
                Shizuku.unbindUserService(args, conn, true)
            } catch (e: Exception) {}
        }
        activeService = null
        activeConnection = null
    }
}
