package wang.yaojia.webterm.api.pairing

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import wang.yaojia.webterm.wire.HostClassifier
import wang.yaojia.webterm.wire.HostEndpoint
import wang.yaojia.webterm.wire.HostNetworkTier

/** Ports the tier table of iOS `HostClassificationTests` (plan §5.4, fail-safe unknown→public). */
class HostClassifierTest {
    @Test
    fun loopbackHostsClassifyAsLoopback() {
        val hosts = listOf("localhost", "LOCALHOST", "127.0.0.1", "127.5.9.200", "::1", "[::1]")
        hosts.forEach { assertEquals(HostNetworkTier.LOOPBACK, HostClassifier.classify(it), it) }
    }

    @Test
    fun rfc1918AndLinkLocalAndMdnsClassifyAsPrivateLan() {
        val hosts = listOf(
            "10.0.0.5", "10.255.255.255",
            "172.16.0.1", "172.20.10.1", "172.31.255.255",
            "192.168.0.9", "192.168.1.1",
            "169.254.1.1",
            "mac-mini.local", "MAC-MINI.LOCAL", "printer.local",
        )
        hosts.forEach { assertEquals(HostNetworkTier.PRIVATE_LAN, HostClassifier.classify(it), it) }
    }

    @Test
    fun cgnatAndMagicDnsClassifyAsTailscale() {
        val hosts = listOf(
            "100.64.0.1", "100.100.1.1", "100.127.255.255",
            "mac.tailnet.ts.net", "MAC.TAILNET.TS.NET", "host.ts.net",
        )
        hosts.forEach { assertEquals(HostNetworkTier.TAILSCALE, HostClassifier.classify(it), it) }
    }

    @Test
    fun everythingElseFailsSafeToPublic() {
        val hosts = listOf(
            // routable public IPs
            "8.8.8.8", "203.0.113.7",
            // hostnames
            "example.com", "claude.ai",
            // boundary-miss IPv4 (just outside the private/tailscale ranges)
            "172.15.0.1", "172.32.0.1", "100.63.0.1", "100.128.0.1",
            // malformed / out-of-range / wrong arity → fail-safe public
            "256.1.1.1", "1.2.3", "999.999.999.999", "not a host", "",
            // non-loopback IPv6 (ULA / documentation) → fail-safe public (iOS v1 scope)
            "fd00::1", "2001:db8::1",
        )
        hosts.forEach { assertEquals(HostNetworkTier.PUBLIC, HostClassifier.classify(it), it) }
    }

    @Test
    fun classifyEndpointDelegatesToHost() {
        val lan = requireNotNull(HostEndpoint.fromBaseUrl("http://192.168.1.5:3000"))
        val tailscale = requireNotNull(HostEndpoint.fromBaseUrl("https://mac.tailnet.ts.net"))
        val public = requireNotNull(HostEndpoint.fromBaseUrl("https://example.com"))

        assertEquals(HostNetworkTier.PRIVATE_LAN, HostClassifier.classify(lan))
        assertEquals(HostNetworkTier.TAILSCALE, HostClassifier.classify(tailscale))
        assertEquals(HostNetworkTier.PUBLIC, HostClassifier.classify(public))
    }
}
