package com.optix.android.tools.osint

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
import org.json.JSONObject

/**
 * EmailRep.io reputation check — queries the public EmailRep API for an address
 * and returns its reputation score, blacklist status, and associated domains.
 */
class EmailRepTool(private val client: OkHttpClient) : BaseTool() {

    override val metadata = ToolMetadata(
        name = "emailrep_check",
        displayName = "EmailRep Reputation",
        description = "Check an email address reputation, blacklist status and associated domains via EmailRep.io",
        category = ToolCategory.DNS_WEB,
        parameters = listOf(
            ToolParam("email", ParamType.STRING, "Email address to inspect"),
        ),
        chainSuggestions = listOf("dehashed_search"),
    )

    override suspend fun execute(params: Map<String, Any>, emit: suspend (ToolEvent) -> Unit) {
        val email = paramRequired(params, "email")
        emit(ToolEvent.Log("[EmailRep] Querying reputation for $email..."))

        withContext(Dispatchers.IO) {
            val request = Request.Builder()
                .url("https://emailrep.io/query/${email.encodeURL()}")
                .header("User-Agent", "OptixV4")
                .build()

            runCatching {
                client.newCall(request).execute().use { response ->
                    when (response.code) {
                        401, 403 -> {
                            emit(ToolEvent.Log(
                                "[EmailRep] API returned ${response.code} — EmailRep may require an API key. " +
                                    "Alternatively try the DeHashed or HaveIBeenPwned tools."
                            ))
                            emit(ToolEvent.Error("EmailRep API access denied (${response.code}). Consider an API key or an alternative source."))
                            return@use
                        }
                    }
                    val body = response.body?.string().orEmpty()
                    if (body.isBlank()) {
                        emit(ToolEvent.Error("Empty response from EmailRep (HTTP ${response.code})."))
                        return@use
                    }
                    val json = JSONObject(body)
                    val reputation = json.optString("reputation", "unknown")
                    val suspicious = json.optBoolean("suspicious", false)
                    val blacklisted = json.optBoolean("blacklisted", false)
                    val malicious = json.optBoolean("malicious", false)
                    val references = json.optInt("references", 0)
                    val details = json.optJSONObject("details")
                    val domains = details?.optJSONArray("domains")

                    emit(ToolEvent.Result(OsintResult("Reputation", reputation, "EmailRep")))
                    emit(ToolEvent.Result(OsintResult("Suspicious", suspicious.toString(), "EmailRep")))
                    emit(ToolEvent.Result(OsintResult("Blacklisted", blacklisted.toString(), "EmailRep")))
                    emit(ToolEvent.Result(OsintResult("Malicious", malicious.toString(), "EmailRep")))
                    emit(ToolEvent.Result(OsintResult("References", references.toString(), "EmailRep")))

                    val domainList = mutableListOf<String>()
                    if (domains != null) {
                        for (i in 0 until domains.length()) {
                            domainList.add(domains.optString(i))
                        }
                    }
                    emit(ToolEvent.Result(OsintResult("Associated Domains", domainList.joinToString(", "), "EmailRep")))

                    emit(ToolEvent.Log(
                        "[EmailRep] reputation=$reputation suspicious=$suspicious blacklisted=$blacklisted " +
                            "domains=${domainList.size}"
                    ))
                }
            }.onFailure {
                emit(ToolEvent.Error("EmailRep request failed: ${it.message}"))
            }
        }

        emit(ToolEvent.ChainSuggestion("dehashed_search", mapOf("query" to email, "queryType" to "email")))
        emit(ToolEvent.Done)
    }

    private fun String.encodeURL(): String =
        java.net.URLEncoder.encode(this, "UTF-8")
}
