package com.system.cloudservice.util

import java.util.concurrent.TimeUnit

object ShellExecutor {

    data class Result(val success: Boolean, val output: String, val isRoot: Boolean = false)

    private val suBins = listOf("/product/bin/su", "/system/bin/su", "/system/xbin/su", "su")

    fun execute(command: String, timeoutSec: Long = 15): Result {
        // 1) try su first (5s timeout — Magisk may show prompt)
        for (su in suBins) {
            runWithTimeout(arrayOf(su, "-c", command), 5)?.let { (code, out, err) ->
                if (code == 0) return Result(true, out.ifEmpty { "ok" }, isRoot = true)
                if (err.contains("not found", ignoreCase = true)) return@let
            }
        }
        // 2) fallback to sh
        runWithTimeout(arrayOf("sh", "-c", command), timeoutSec)?.let { (code, out, err) ->
            return if (code == 0) Result(true, out.ifEmpty { "ok" })
            else Result(false, err.ifEmpty { "exit $code" })
        }
        return Result(false, "timeout")
    }

    fun hasRoot(): Boolean {
        for (su in suBins) {
            val ok = runWithTimeout(arrayOf(su, "-c", "id"), 10)?.let { (code, out, err) ->
                code == 0 && (out.contains("uid=0") || out.contains("uid=0(")) &&
                    !err.contains("denied", ignoreCase = true)
            } ?: false
            if (ok) return true
        }
        return false
    }

    private fun runWithTimeout(
        cmd: Array<String>, timeoutSec: Long
    ): Triple<Int, String, String>? {
        return try {
            val p = Runtime.getRuntime().exec(cmd)
            if (!p.waitFor(timeoutSec, TimeUnit.SECONDS)) {
                p.destroyForcibly(); return null
            }
            Triple(
                p.exitValue(),
                p.inputStream.bufferedReader().readText().trim(),
                p.errorStream.bufferedReader().readText().trim()
            )
        } catch (_: Exception) { null }
    }
}
