import pytest
import os
import sys
from unittest.mock import patch, mock_open

# Add the parent directory to the path so we can import from ipv6_utils
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from utils import build_api_url


class TestConfigIPv6Support:
    """Test IPv6 address handling for rack awareness"""

    def test_ipv4_address_url_construction(self):
        """Test that IPv4 addresses are handled correctly in Kubernetes API calls"""
        service_host = "192.168.1.1"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://192.168.1.1:443/api/v1/"
        assert api_url == expected

    def test_ipv6_full_address_url_construction(self):
        """Test that full IPv6 addresses are wrapped in brackets"""
        service_host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:443/api/v1/"
        assert api_url == expected

    def test_ipv6_shortened_address_url_construction(self):
        """Test shortened IPv6 addresses (common in Kubernetes)"""
        service_host = "2001:db8::1"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://[2001:db8::1]:443/api/v1/"
        assert api_url == expected

    def test_ipv6_localhost_url_construction(self):
        """Test IPv6 localhost address"""
        service_host = "::1"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://[::1]:443/api/v1/"
        assert api_url == expected

    def test_ipv6_dual_stack_common_addresses(self):
        """Test common IPv6 addresses used in dual-stack Kubernetes clusters"""
        test_cases = [
            ("fd00::1", "https://[fd00::1]:443/api/v1/"),  # ULA address
            ("fe80::1", "https://[fe80::1]:443/api/v1/"),  # Link-local
            ("2001:db8:85a3::8a2e:370:7334", "https://[2001:db8:85a3::8a2e:370:7334]:443/api/v1/"),  # Compressed
        ]

        for service_host, expected in test_cases:
            api_url = build_api_url(service_host, "443")
            assert api_url == expected, f"Failed for {service_host}"

    def test_hostname_url_construction(self):
        """Test that hostnames (FQDN) are handled correctly"""
        service_host = "kubernetes.default.svc.cluster.local"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://kubernetes.default.svc.cluster.local:443/api/v1/"
        assert api_url == expected

    def test_invalid_ip_fallback_to_hostname(self):
        """Test that invalid IP addresses are treated as hostnames"""
        service_host = "not.an.ip.address"
        tcp_port = "443"

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://not.an.ip.address:443/api/v1/"
        assert api_url == expected

    def test_kubernetes_service_ports(self):
        """Test with actual Kubernetes service port values"""
        service_host = "2001:db8::1"  # Use valid IPv6 address

        # Test common Kubernetes API server ports
        test_ports = ["443", "6443", "8443"]
        for port in test_ports:
            api_url = build_api_url(service_host, port)
            expected = f"https://[2001:db8::1]:{port}/api/v1/"
            assert api_url == expected

    def test_rack_awareness_api_urls(self):
        """Test the specific API URLs used in rack awareness logic"""
        service_host = "2001:db8::1"
        tcp_port = "443"
        namespace = "confluent"
        hostname = "kafka-0"
        node_name = "ip-192-168-1-10.us-west-2.compute.internal"

        base_url = build_api_url(service_host, tcp_port)

        # Test pod API URL
        pod_url = base_url + 'namespaces/%s/pods/%s' % (namespace, hostname)
        expected_pod_url = "https://[2001:db8::1]:443/api/v1/namespaces/confluent/pods/kafka-0"
        assert pod_url == expected_pod_url

        # Test node API URL
        node_url = base_url + 'nodes/%s' % node_name
        expected_node_url = "https://[2001:db8::1]:443/api/v1/nodes/ip-192-168-1-10.us-west-2.compute.internal"
        assert node_url == expected_node_url

    def test_edge_case_ipv6_addresses(self):
        """Test edge cases for IPv6 address parsing"""
        edge_cases = [
            ("::ffff:192.0.2.1", "https://[::ffff:192.0.2.1]:443/api/v1/"),  # IPv4-mapped IPv6
            ("::", "https://[::]:443/api/v1/"),  # All zeros
            ("::ffff:0:0", "https://[::ffff:0:0]:443/api/v1/"),  # IPv4-mapped zeros
        ]

        for service_host, expected in edge_cases:
            api_url = build_api_url(service_host, "443")
            assert api_url == expected, f"Failed for edge case: {service_host}"

    @patch.dict(os.environ, {
        'RACK_NODE_LABELS': '["topology.kubernetes.io/zone"]',
        'KUBERNETES_SERVICE_HOST': '2001:db8::1',
        'KUBERNETES_SERVICE_PORT_HTTPS': '443',
        'HOSTNAME': 'kafka-0',
        'POD_NAMESPACE': 'confluent'
    })
    @patch('builtins.open', mock_open(read_data='fake-token'))
    def test_environment_variables_ipv6_integration(self):
        """Test that environment variables work correctly with IPv6"""
        # Verify environment is set up correctly for IPv6
        assert os.environ['KUBERNETES_SERVICE_HOST'] == '2001:db8::1'

        # Test URL construction with environment variables
        service_host = os.environ['KUBERNETES_SERVICE_HOST']
        tcp_port = os.environ['KUBERNETES_SERVICE_PORT_HTTPS']

        api_url = build_api_url(service_host, tcp_port)
        expected = "https://[2001:db8::1]:443/api/v1/"
        assert api_url == expected
