package com.optix.android.ai

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 com.optix.android.tools.registry.ToolRegistry
import com.optix.android.util.NetworkUtils
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Test

/**
 * Fake tool used only to populate the ToolRegistry with a known name so MockBrain
 * can resolve tool calls. validate() passes; execute() is never invoked by MockBrain.
 */
private class NamedFakeTool(toolName: String) : BaseTool() {
    override val metadata: ToolMetadata = ToolMetadata(
        name = toolName,
        displayName = toolName,
        description = "fake",
        category = ToolCategory.NETWORK_SCANNING,
        parameters = emptyList(),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {}
}

/**
 * Fake NetworkUtils. The real getLocalNetworkState() touches Android APIs; we override it
 * to return a fixed subnet so MockBrain's localSubnet() resolves deterministically.
 */
private class FakeNetworkUtils : NetworkUtils(FakeContext()) {
    override fun getLocalNetworkState(): NetworkUtils.NetworkState =
        NetworkUtils.NetworkState(subnet = "192.168.1")
}

class MockBrainTest {

    private fun buildBrain(): MockBrain {
        val registry = ToolRegistry()
        registry.register(NamedFakeTool("lan_scanner"))
        registry.register(NamedFakeTool("port_scanner"))
        registry.register(NamedFakeTool("nmap_termux"))
        registry.register(NamedFakeTool("ssh_audit"))
        registry.register(NamedFakeTool("linpeas_termux"))
        registry.register(NamedFakeTool("winpeas_termux"))
        registry.register(NamedFakeTool("cme_termux"))
        registry.register(NamedFakeTool("bloodhound_termux"))
        registry.register(NamedFakeTool("nuclei_termux"))
        registry.register(NamedFakeTool("dns_recon"))

        return MockBrain(FakeNetworkUtils(), registry)
    }

    @Test
    fun respond_lanScan_returnsLanScanner() {
        val r = buildBrain().respond("lan scan")
        assertNotNull(r.toolCall)
        assertEquals("lan_scanner", r.toolCall!!.first)
    }

    @Test
    fun respond_portScan_returnsPortScanner() {
        val r = buildBrain().respond("port scan 192.168.1.1")
        assertNotNull(r.toolCall)
        assertEquals("port_scanner", r.toolCall!!.first)
    }

    @Test
    fun respond_nmap_returnsNmapTermux() {
        val r = buildBrain().respond("nmap 10.0.0.1")
        assertNotNull(r.toolCall)
        assertEquals("nmap_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_sshAudit_returnsSshAudit() {
        val r = buildBrain().respond("ssh audit 1.2.3.4")
        assertNotNull(r.toolCall)
        assertEquals("ssh_audit", r.toolCall!!.first)
    }

    @Test
    fun respond_linpeas_returnsLinpeasTermux() {
        val r = buildBrain().respond("linpeas")
        assertNotNull(r.toolCall)
        assertEquals("linpeas_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_winpeas_returnsWinpeasTermux() {
        val r = buildBrain().respond("winpeas 1.2.3.4")
        assertNotNull(r.toolCall)
        assertEquals("winpeas_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_cme_returnsCmeTermux() {
        val r = buildBrain().respond("cme 1.2.3.4")
        assertNotNull(r.toolCall)
        assertEquals("cme_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_bloodhound_returnsBloodhoundTermux() {
        val r = buildBrain().respond("bloodhound")
        assertNotNull(r.toolCall)
        assertEquals("bloodhound_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_nuclei_returnsNucleiTermux() {
        val r = buildBrain().respond("nuclei https://example.com")
        assertNotNull(r.toolCall)
        assertEquals("nuclei_termux", r.toolCall!!.first)
    }

    @Test
    fun respond_dns_returnsDnsRecon() {
        val r = buildBrain().respond("dns google.com")
        assertNotNull(r.toolCall)
        assertEquals("dns_recon", r.toolCall!!.first)
    }
}
