package com.optix.android.domain.model

import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException

object ResultSerialization {

    fun decodeResult(gson: Gson, toolSlug: String, json: String): Any? = runCatching {
        // Tools that emit heterogeneous structured findings (item #12): a single
        // session can contain OpenPort / ServiceInfo / VulnerabilityFinding rows,
        // so decode by JSON shape rather than a fixed per-slug type.
        when (toolSlug) {
            "nmap_termux", "ssh_audit", "http_inspector", "nuclei_termux" ->
                decodeParsedFinding(gson, json) ?: gson.fromJson(json, Any::class.java)
            "network_scanner", "lan_scanner", "netbios_scanner" ->
                gson.fromJson(json, HostResult::class.java)
            "port_scanner" ->
                gson.fromJson(json, PortResult::class.java)
            "dns_recon" ->
                gson.fromJson(json, DnsRecord::class.java)
            "subdomain_enum" ->
                gson.fromJson(json, SubdomainResult::class.java)
            "directory_fuzzer" ->
                gson.fromJson(json, DirectoryResult::class.java)
            "ssl_inspector" ->
                gson.fromJson(json, SslResult::class.java)
            "cve_lookup" ->
                gson.fromJson(json, VulnResult::class.java)
            "hash_cracker" ->
                gson.fromJson(json, HashResult::class.java)
            "whois_lookup", "ip_geolocation", "email_header_analyzer", "username_search",
            "email_osint", "phone_lookup", "breach_check", "whois_history", "crtsh",
            "wayback_machine", "shodan_search", "ip_reputation", "github_osint",
            "pastebin_search", "dark_web_monitor", "censys_search", "alienvault_otx",
            "greynoise_ip", "urlscan_io", "google_dork_builder", "metadata_extractor",
            "the_harvester" ->
                gson.fromJson(json, OsintResult::class.java)
            else ->
                gson.fromJson(json, Any::class.java)
        }
    }.getOrElse {
        runCatching { gson.fromJson(json, Any::class.java) }.getOrNull()
    }

    /**
     * Decodes one of the parsing-layer models by inspecting the JSON keys.
     * Returns null when the shape matches none of them so the caller can fall
     * back to a generic decode.
     */
    private fun decodeParsedFinding(gson: Gson, json: String): Any? {
        val obj = runCatching { gson.fromJson(json, JsonObject::class.java) }
            .getOrElse { if (it is JsonSyntaxException) return null else throw it }
            ?: return null
        return when {
            obj.has("severity") && obj.has("title") && obj.has("tool") ->
                gson.fromJson(json, VulnerabilityFinding::class.java)
            obj.has("port") && obj.has("host") && obj.has("state") ->
                gson.fromJson(json, OpenPort::class.java)
            obj.has("service") && obj.has("host") ->
                gson.fromJson(json, ServiceInfo::class.java)
            obj.has("field") && obj.has("value") && obj.has("source") ->
                gson.fromJson(json, OsintResult::class.java)
            else -> null
        }
    }
}
