package com.optix.android.tools.web

import com.optix.android.domain.model.OsintResult
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 okhttp3.OkHttpClient
import okhttp3.Request

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

    override val metadata = ToolMetadata(
        name = "xss_scanner",
        displayName = "XSS Scanner",
        description = "Test URL parameters for reflected XSS vulnerabilities",
        category = ToolCategory.DNS_WEB,
        parameters = listOf(
            ToolParam("url", ParamType.STRING, "Target URL with query parameters"),
            ToolParam("param", ParamType.STRING, "Parameter name to test", required = false, defaultValue = "q"),
        ),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val url = paramRequired(params, "url")
        val param = param(params, "param") ?: "q"

        emit(ToolEvent.Log("Testing $url for XSS on param '$param'"))

        withContext(Dispatchers.IO) {
            PAYLOADS.forEach { payload ->
                val testUrl = if (url.contains("?")) "$url&$param=${payload}" else "$url?$param=${payload}"
                runCatching {
                    val request = Request.Builder().url(testUrl).build()
                    client.newCall(request).execute().use { response ->
                        val body = response.body?.string() ?: ""
                        if (payload in body) {
                            emit(ToolEvent.Result(OsintResult("XSS", "Reflected payload: $payload", testUrl)))
                            emit(ToolEvent.Log("  [VULN] Payload reflected: $payload"))
                        } else {
                            emit(ToolEvent.Log("  [OK]   $payload"))
                        }
                    }
                }.onFailure { emit(ToolEvent.Log("  [ERR]  $payload: ${it.message}")) }
            }
        }

        emit(ToolEvent.ChainSuggestion("sqli_tester", mapOf("url" to url)))
        emit(ToolEvent.Done)
    }

    companion object {
        val PAYLOADS = listOf(
            "<script>alert(1)</script>",
            "\"><script>alert(1)</script>",
            "'><img src=x onerror=alert(1)>",
            "<svg onload=alert(1)>",
        )
    }
}
