"""Tests for network_utils module - IP address classification."""

from local_deep_research.security.network_utils import is_private_ip


class TestIsPrivateIPLocalhost:
    """Tests for localhost detection."""

    def test_localhost_string(self):
        """Should detect 'localhost' as private."""
        assert is_private_ip("localhost") is True

    def test_loopback_ipv4(self):
        """Should detect 127.0.0.1 as private."""
        assert is_private_ip("127.0.0.1") is True

    def test_loopback_ipv6_bracketed(self):
        """Should detect [::1] as private."""
        assert is_private_ip("[::1]") is True

    def test_all_zeros_ipv4(self):
        """Should detect 0.0.0.0 as private."""
        assert is_private_ip("0.0.0.0") is True


class TestIsPrivateIPIPv4Ranges:
    """Tests for IPv4 private address range detection."""

    def test_10_0_0_0_range(self):
        """Should detect 10.x.x.x as private (RFC 1918)."""
        assert is_private_ip("10.0.0.1") is True
        assert is_private_ip("10.255.255.255") is True
        assert is_private_ip("10.100.50.25") is True

    def test_172_16_0_0_range(self):
        """Should detect 172.16-31.x.x as private (RFC 1918)."""
        assert is_private_ip("172.16.0.1") is True
        assert is_private_ip("172.31.255.255") is True
        assert is_private_ip("172.20.10.5") is True

    def test_192_168_0_0_range(self):
        """Should detect 192.168.x.x as private (RFC 1918)."""
        assert is_private_ip("192.168.0.1") is True
        assert is_private_ip("192.168.255.255") is True
        assert is_private_ip("192.168.1.100") is True

    def test_link_local_range(self):
        """Should detect 169.254.x.x as private (link-local)."""
        assert is_private_ip("169.254.1.1") is True
        assert is_private_ip("169.254.255.255") is True

    def test_loopback_range(self):
        """Should detect 127.x.x.x as private (loopback)."""
        assert is_private_ip("127.0.0.1") is True
        assert is_private_ip("127.255.255.255") is True
        assert is_private_ip("127.100.50.25") is True


class TestIsPrivateIPIPv6:
    """Tests for IPv6 private address detection."""

    def test_ipv6_loopback(self):
        """Should detect IPv6 loopback as private."""
        assert is_private_ip("::1") is True

    def test_ipv6_unique_local(self):
        """Should detect fc00::/7 as private (unique local)."""
        assert is_private_ip("fc00::1") is True
        assert is_private_ip("fd00::1") is True

    def test_ipv6_link_local(self):
        """Should detect fe80::/10 as private (link-local)."""
        assert is_private_ip("fe80::1") is True

    def test_ipv6_bracketed(self):
        """Should handle bracketed IPv6 addresses."""
        assert is_private_ip("[::1]") is True
        assert is_private_ip("[fc00::1]") is True
        assert is_private_ip("[fe80::1]") is True


class TestIsPrivateIPPublicAddresses:
    """Tests for public address detection."""

    def test_public_ipv4_google_dns(self):
        """Should not detect Google DNS (8.8.8.8) as private."""
        assert is_private_ip("8.8.8.8") is False

    def test_public_ipv4_cloudflare_dns(self):
        """Should not detect Cloudflare DNS (1.1.1.1) as private."""
        assert is_private_ip("1.1.1.1") is False

    def test_public_ipv4_example(self):
        """Should not detect example.com IP as private."""
        assert is_private_ip("93.184.216.34") is False

    def test_public_ipv4_various(self):
        """Should not detect various public IPs as private."""
        # Note: 203.0.113.x is TEST-NET-3 (RFC 5737), considered private/reserved
        assert is_private_ip("104.26.10.222") is False  # Cloudflare
        assert is_private_ip("142.250.190.46") is False  # Google
        assert is_private_ip("151.101.1.140") is False  # Reddit

    def test_public_ipv6(self):
        """Should not detect public IPv6 addresses as private."""
        assert is_private_ip("2001:4860:4860::8888") is False  # Google DNS
        assert is_private_ip("2606:4700:4700::1111") is False  # Cloudflare


class TestIsPrivateIPHostnames:
    """Tests for hostname handling."""

    def test_public_hostname(self):
        """Should not detect public hostnames as private."""
        assert is_private_ip("example.com") is False
        assert is_private_ip("api.openai.com") is False
        assert is_private_ip("google.com") is False

    def test_local_domain(self):
        """Should detect .local domains as private (mDNS)."""
        assert is_private_ip("mydevice.local") is True
        assert is_private_ip("printer.local") is True
        assert is_private_ip("server.local") is True

    def test_local_domain_case_sensitive(self):
        """Should only match lowercase .local."""
        # Note: actual behavior depends on implementation
        # The current implementation is case-sensitive for .local
        assert is_private_ip("mydevice.local") is True
        # These won't match the .local check, but aren't valid IPs either
        # so they'll return False

    def test_internal_subdomain(self):
        """Should not detect internal.corp as private (no DNS resolution)."""
        # The function doesn't resolve DNS for security reasons
        assert is_private_ip("internal.corp") is False
        assert is_private_ip("server.internal") is False


class TestIsPrivateIPEdgeCases:
    """Tests for edge cases."""

    def test_172_15_not_private(self):
        """172.15.x.x should NOT be private (only 172.16-31 are)."""
        # This is technically public IP space
        assert is_private_ip("172.15.0.1") is False

    def test_172_32_not_private(self):
        """172.32.x.x should NOT be private (only 172.16-31 are)."""
        assert is_private_ip("172.32.0.1") is False

    def test_empty_string(self):
        """Should handle empty string."""
        # Empty string is not a valid IP and doesn't end with .local
        assert is_private_ip("") is False

    def test_invalid_ip_format(self):
        """Should handle invalid IP formats."""
        assert is_private_ip("not.an.ip.address") is False
        assert is_private_ip("256.256.256.256") is False
        assert is_private_ip("192.168.1") is False
