package com.optix.android.tools.web

import com.optix.android.domain.model.DnsRecord
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.withContext
import org.xbill.DNS.Lookup
import org.xbill.DNS.Type

class DnsReconTool : BaseTool() {

    override val metadata = ToolMetadata(
        name = "dns_recon",
        displayName = "DNS Recon",
        description = "Full DNS record lookup — A, MX, NS, TXT, CNAME, AAAA",
        category = ToolCategory.DNS_WEB,
        parameters = listOf(
            ToolParam("domain", ParamType.STRING, "Target domain"),
            ToolParam("record_types", ParamType.STRING, "Comma-separated record types", required = false, defaultValue = "A,MX,NS,TXT,CNAME"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val domain = paramRequired(params, "domain")
        val types = (param(params, "record_types") ?: "A,MX,NS,TXT,CNAME").split(",").map { it.trim() }

        emit(ToolEvent.Log("DNS recon: $domain"))

        withContext(Dispatchers.IO) {
            for (typeName in types) {
                val typeCode = runCatching { Type.value(typeName) }.getOrDefault(Type.A)
                runCatching {
                    val records = Lookup(domain, typeCode).run() ?: emptyArray()
                    for (record in records) {
                        val value = record.rdataToString()
                        emit(ToolEvent.Result(DnsRecord(typeName, domain, value, record.ttl.toInt())))
                        emit(ToolEvent.Log("  $typeName  $value"))
                    }
                    if (records.isEmpty()) emit(ToolEvent.Log("  $typeName  (no records)"))
                }.onFailure { emit(ToolEvent.Log("  $typeName  lookup failed: ${it.message}")) }
            }
        }

        emit(ToolEvent.ChainSuggestion("subdomain_enum", mapOf("domain" to domain)))
        emit(ToolEvent.Done)
    }
}
