package com.optix.android.tools.web

import com.optix.android.domain.model.ParamType
import com.optix.android.domain.model.SubdomainResult
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.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.InetAddress

class SubdomainEnumTool(private val client: OkHttpClient) : BaseTool() {

    override val metadata = ToolMetadata(
        name = "subdomain_enum",
        displayName = "Subdomain Enum",
        description = "Enumerate subdomains via wordlist brute-force and DNS resolution",
        category = ToolCategory.DNS_WEB,
        parameters = listOf(
            ToolParam("domain", ParamType.STRING, "Target domain"),
            ToolParam("wordlist", ParamType.STRING, "Comma-separated subdomain prefixes", required = false, defaultValue = "www,mail,ftp,api,dev,staging,admin,vpn,remote,test"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val domain = paramRequired(params, "domain")
        val wordlist = (param(params, "wordlist") ?: DEFAULT_WORDLIST).split(",").map { it.trim() }

        emit(ToolEvent.Log("Enumerating subdomains for $domain (${wordlist.size} candidates)"))

        coroutineScope {
            wordlist.mapIndexed { idx, prefix ->
                async(Dispatchers.IO) {
                    val subdomain = "$prefix.$domain"
                    val ip = runCatching { InetAddress.getByName(subdomain).hostAddress }.getOrNull()
                    if (ip != null) {
                        emit(ToolEvent.Result(SubdomainResult(subdomain, ip)))
                        emit(ToolEvent.Log("  $subdomain  $ip"))
                    }
                    emit(ToolEvent.Progress(idx + 1, wordlist.size))
                }
            }.awaitAll()
        }

        emit(ToolEvent.ChainSuggestion("http_inspector", mapOf("url" to "https://$domain")))
        emit(ToolEvent.Done)
    }

    companion object {
        const val DEFAULT_WORDLIST = "www,mail,ftp,api,dev,staging,admin,vpn,remote,test,blog,shop,app,portal,secure,login,auth,cdn,static,media"
    }
}
