package com.optix.android.tools.cloud

import com.optix.android.domain.model.ParamType
import com.optix.android.domain.model.ToolCategory
import com.optix.android.domain.model.ToolEvent
import com.optix.android.domain.model.ToolMetadata
import com.optix.android.domain.model.ToolParam
import com.optix.android.tools.engine.EnvironmentManager
import com.optix.android.tools.engine.ShellExecutor
import com.optix.android.tools.registry.BaseTool
import javax.inject.Inject

/**
 * Docker inspection tool — enumerates images, containers, networks, and
 * volumes and highlights insecure runtime configurations.
 *
 * Read-only: uses `docker ps`/`inspect`/`images` only; never starts, stops, or
 * deletes containers. Requires the `docker` CLI available in Termux (or a remote
 * daemon reachable via DOCKER_HOST).
 *
 * AUTHORIZED TESTING ONLY.
 */
class DockerInspectTool @Inject constructor(
    private val shell: ShellExecutor,
) : BaseTool() {

    override val metadata = ToolMetadata(
        name = "docker_inspect_termux",
        displayName = "Docker Inspect (Termux)",
        description = "Read-only Docker host inspection: list images, running/stopped containers, networks, and volumes; flag privileged containers, mounted host paths, and exposed ports.",
        category = ToolCategory.CONTAINER_SEC,
        parameters = listOf(
            ToolParam(
                name = "host",
                type = ParamType.STRING,
                description = "Remote Docker daemon (DOCKER_HOST), e.g. tcp://10.0.0.5:2375",
                required = false,
                defaultValue = "",
            ),
            ToolParam(
                name = "show_all",
                type = ParamType.BOOLEAN,
                description = "Include stopped containers",
                required = false,
                defaultValue = "true",
            ),
        ),
        requiresRoot = false,
        requiresNetwork = true,
        requiresTermux = true,
        requiredPackages = listOf("docker"),
        supportedPlatforms = listOf("Android", "Linux", "macOS"),
        chainSuggestions = listOf("kube_recon_termux", "network_scanner"),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val host = param(params, "host") ?: ""
        val showAll = paramBool(params, "show_all", true)

        emit(ToolEvent.Log("🐳 Docker inspection starting..."))
        if (host.isNotBlank()) emit(ToolEvent.Log("DOCKER_HOST: $host"))
        emit(ToolEvent.Log(""))

        val probe = shell.exec("${EnvironmentManager.TERMUX_BIN}/docker version --format {{(.Server.Version)}}", root = false)
        if (probe.stdout.contains("command not found", true) || (probe.exitCode != 0 && probe.stdout.isBlank())) {
            emit(ToolEvent.TermuxMissing("docker", "docker"))
            emit(ToolEvent.Error("docker not found in Termux. Install it: pkg install docker"))
            emit(ToolEvent.Done)
            return
        }

        val envPrefix = if (host.isNotBlank()) "DOCKER_HOST=$host " else ""

        runCatching {
            shell.exec("${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker images", root = false, timeoutMs = 30_000)
                .also { it.stdout.lineSequence().filter { l -> l.isNotBlank() }.forEach { emit(ToolEvent.Log(it)) } }
            val psCmd = if (showAll) "ps -a --format table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
                         else "ps --format table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
            shell.exec("${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker $psCmd", root = false, timeoutMs = 30_000)
                .also { it.stdout.lineSequence().filter { l -> l.isNotBlank() }.forEach { emit(ToolEvent.Log(it)) } }
            shell.exec("${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker network ls", root = false, timeoutMs = 30_000)
                .also { it.stdout.lineSequence().filter { l -> l.isNotBlank() }.forEach { emit(ToolEvent.Log(it)) } }
            shell.exec("${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker volume ls", root = false, timeoutMs = 30_000)
                .also { it.stdout.lineSequence().filter { l -> l.isNotBlank() }.forEach { emit(ToolEvent.Log(it)) } }

            // Flag privileged containers (misconfiguration signal).
            val ids = shell.exec(
                "${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker ps -aq -f status=running",
                root = false, timeoutMs = 30_000,
            ).stdout.lines().filter { it.isNotBlank() }
            ids.forEach { id ->
                val info = shell.exec(
                    "${envPrefix}${EnvironmentManager.TERMUX_BIN}/docker inspect --format " +
                        "'PRIV={{.HostConfig.Privileged}} MOUNTS={{json .Mounts}} PORTS={{json .NetworkSettings.Ports}} NAME={{.Name}}' $id",
                    root = false, timeoutMs = 30_000,
                ).stdout
                if (info.contains("PRIV=true")) {
                    emit(ToolEvent.Log("⚠️ Privileged container: $info"))
                    emit(ToolEvent.Result(
                        com.optix.android.domain.model.OsintResult("Docker", info, "docker_inspect")
                    ))
                }
            }

            emit(ToolEvent.Log(""))
            emit(ToolEvent.Log("✅ Docker inspection complete (read-only)."))
        }.onFailure {
            emit(ToolEvent.Error("Docker inspection failed: ${it.message}"))
        }

        emit(ToolEvent.Done)
    }
}
