package com.optix.android.tools.parser

import com.optix.android.domain.model.Severity
import com.optix.android.domain.model.ServiceInfo
import com.optix.android.domain.model.VulnerabilityFinding

/**
 * Pure parser for an SSH banner string (e.g. "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6").
 *
 * Produces a [ServiceInfo] describing the server plus zero or more
 * [VulnerabilityFinding]s for weak/outdated configurations. No Android or
 * network dependency — the SSH tool grabs the banner, this decides what it means.
 */
object SshBannerParser {

    data class SshAudit(
        val service: ServiceInfo,
        val findings: List<VulnerabilityFinding>,
    )

    private val OUTDATED_VERSIONS = mapOf(
        "openssh_3" to (Severity.CRITICAL to "OpenSSH 3.x — critically outdated, update immediately"),
        "openssh_4" to (Severity.CRITICAL to "OpenSSH 4.x — very outdated, update immediately"),
        "openssh_5" to (Severity.HIGH to "OpenSSH 5.x — outdated, multiple known CVEs"),
        "openssh_6" to (Severity.MEDIUM to "OpenSSH 6.x — update recommended"),
        "openssh_7" to (Severity.LOW to "OpenSSH 7.x — check for CVE-2018-15473 (user enumeration)"),
        "dropbear" to (Severity.MEDIUM to "Dropbear SSH — common on routers/IoT, check for CVE-2016-7406"),
    )

    fun parse(banner: String, host: String, port: Int = 22): SshAudit {
        val trimmed = banner.trim()
        val lower = trimmed.lowercase()

        val software = trimmed.substringAfter("SSH-2.0-", "")
            .ifBlank { trimmed.substringAfter("SSH-1.0-", "") }
            .ifBlank { trimmed.substringAfter("SSH-1.99-", "") }
            .trim()

        val product = software.substringBefore('_', software).substringBefore(' ').ifBlank { null }
        val version = software.substringAfter('_', "").ifBlank { null }

        val service = ServiceInfo(
            host = host,
            port = port,
            service = "ssh",
            product = product,
            version = version,
            banner = trimmed.ifBlank { null },
        )

        val findings = mutableListOf<VulnerabilityFinding>()

        if (trimmed.contains("SSH-1", ignoreCase = true) && !trimmed.contains("SSH-1.99", true)) {
            findings += VulnerabilityFinding(
                tool = "ssh_audit",
                target = "$host:$port",
                severity = Severity.CRITICAL,
                title = "SSHv1 protocol enabled",
                detail = "SSHv1 is vulnerable to man-in-the-middle attacks and should be disabled.",
            )
        }

        OUTDATED_VERSIONS.forEach { (key, sev) ->
            if (lower.contains(key)) {
                findings += VulnerabilityFinding(
                    tool = "ssh_audit",
                    target = "$host:$port",
                    severity = sev.first,
                    title = "Outdated SSH software",
                    detail = sev.second,
                )
            }
        }

        return SshAudit(service, findings)
    }
}
