package com.optix.android.tools.engine

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class EnvironmentManager @Inject constructor() {

    suspend fun isRootAvailable(): Boolean = withContext(Dispatchers.IO) {
        try {
            val process = ProcessBuilder("su", "-c", "id").start()
            val exitCode = process.waitFor()
            exitCode == 0
        } catch (e: Exception) {
            false
        }
    }

    fun isTermuxInstalled(): Boolean {
        return File("/data/data/com.termux/files/usr/bin").exists()
    }

    fun getTermuxPath(): String = "/data/data/com.termux/files/usr/bin"

    suspend fun isBinaryAvailable(binaryName: String): Boolean = withContext(Dispatchers.IO) {
        try {
            val termuxPath = getTermuxPath()
            val binaryFile = File(termuxPath, binaryName)
            binaryFile.exists() && binaryFile.canExecute()
        } catch (e: Exception) {
            false
        }
    }

    /**
     * Returns true when the given tool's required capabilities are satisfied.
     * - [com.optix.android.domain.model.ToolMetadata.requiresRoot] requires root.
     * - [com.optix.android.domain.model.ToolMetadata.requiresTermux] requires Termux.
     */
    suspend fun isCapabilitySatisfied(
        requiresRoot: Boolean,
        requiresTermux: Boolean,
    ): Boolean {
        if (requiresRoot && !isRootAvailable()) return false
        if (requiresTermux && !isTermuxInstalled()) return false
        return true
    }

    /**
     * Attempts to install a single Termux package via `pkg install -y`.
     * Returns true when the package is available afterwards (or was already present).
     * Never throws — callers surface the boolean as a user-facing status.
     */
    suspend fun installTermuxPackage(
        aptPackage: String,
        onLog: suspend (String) -> Unit = {},
    ): Boolean = withContext(Dispatchers.IO) {
        if (!isTermuxInstalled()) {
            onLog("Termux is not installed — cannot install '$aptPackage'. Install Termux from F-Droid.")
            return@withContext false
        }
        val pkgBinary = "$termuxPkgPath"
        try {
            onLog("Installing '$aptPackage' via Termux...")
            val process = ProcessBuilder("su", "-c", "$pkgBinary install -y $aptPackage")
                .redirectErrorStream(true)
                .start()
            process.inputStream.bufferedReader().useLines { lines ->
                lines.forEach { line -> if (line.isNotBlank()) onLog(line) }
            }
            process.waitFor()
            onLog("Finished installing '$aptPackage'.")
            true
        } catch (e: Exception) {
            onLog("Failed to install '$aptPackage': ${e.message}")
            false
        }
    }

    private val termuxPkgPath: String
        get() = "$TERMUX_BIN/pkg"

    companion object {
        const val TERMUX_BIN = "/data/data/com.termux/files/usr/bin"
    }
}
