"""Test HTTP utility functions."""

from unittest import mock

import pytest

from databuilder_logic_sdk.utils.http_utils import build_base_url


class TestBuildBaseUrl:
    """Test build_base_url function."""

    def test_build_base_url_with_http(self) -> None:
        """Test building URL with http protocol."""
        url = build_base_url("http://example.com")
        assert url == "http://example.com"

    def test_build_base_url_with_https(self) -> None:
        """Test building URL with https protocol."""
        url = build_base_url("https://example.com")
        assert url == "https://example.com"

    def test_build_base_url_without_protocol(self) -> None:
        """Test building URL without protocol defaults to http."""
        url = build_base_url("example.com")
        assert url == "http://example.com"

    def test_build_base_url_with_port(self) -> None:
        """Test building URL with port number."""
        url = build_base_url("example.com:8080")
        assert url == "http://example.com:8080"

    def test_build_base_url_with_https_and_port(self) -> None:
        """Test building URL with https and port."""
        url = build_base_url("https://example.com:8443")
        assert url == "https://example.com:8443"

    def test_build_base_url_with_path(self) -> None:
        """Test building URL with path component."""
        url = build_base_url("example.com/api/v1")
        assert url == "http://example.com/api/v1"

    def test_build_base_url_with_trailing_slash(self) -> None:
        """Test building URL with trailing slash."""
        url = build_base_url("example.com/")
        assert url == "http://example.com/"

    def test_build_base_url_with_ip_address(self) -> None:
        """Test building URL with IP address."""
        url = build_base_url("192.168.1.1")
        assert url == "http://192.168.1.1"

    def test_build_base_url_with_ip_and_port(self) -> None:
        """Test building URL with IP address and port."""
        url = build_base_url("192.168.1.1:8080")
        assert url == "http://192.168.1.1:8080"

    def test_build_base_url_with_localhost(self) -> None:
        """Test building URL with localhost."""
        url = build_base_url("localhost:3000")
        assert url == "http://localhost:3000"

    def test_build_base_url_with_subdomain(self) -> None:
        """Test building URL with subdomain."""
        url = build_base_url("api.example.com")
        assert url == "http://api.example.com"

    def test_build_base_url_preserves_existing_protocol(self) -> None:
        """Test that existing protocol is preserved."""
        url = build_base_url("https://secure.example.com:443/api")
        assert url == "https://secure.example.com:443/api"

    def test_build_base_url_with_query_params(self) -> None:
        """Test building URL with query parameters."""
        url = build_base_url("example.com/api?key=value")
        assert url == "http://example.com/api?key=value"

    def test_build_base_url_with_fragment(self) -> None:
        """Test building URL with fragment."""
        url = build_base_url("example.com/page#section")
        assert url == "http://example.com/page#section"

    def test_build_base_url_empty_string(self) -> None:
        """Test building URL with empty string."""
        url = build_base_url("")
        assert url == "http://"

    def test_build_base_url_whitespace(self) -> None:
        """Test building URL with whitespace."""
        url = build_base_url("  example.com  ")
        # 假设函数会处理空白字符
        assert url in ["http://example.com", "http://  example.com  "]

    def test_build_base_url_case_insensitive_protocol(self) -> None:
        """Test that protocol is case insensitive."""
        url = build_base_url("HTTP://example.com")
        assert url == "HTTP://example.com"

    def test_build_base_url_with_authentication(self) -> None:
        """Test building URL with authentication."""
        url = build_base_url("https://user:pass@example.com")
        assert url == "https://user:pass@example.com"

    def test_build_base_url_with_ipv6(self) -> None:
        """Test building URL with IPv6 address."""
        url = build_base_url("[::1]:8080")
        assert url == "http://[::1]:8080"

    def test_build_base_url_with_special_characters(self) -> None:
        """Test building URL with special characters in path."""
        url = build_base_url("example.com/api/v1/users/123")
        assert url == "http://example.com/api/v1/users/123"

    def test_build_base_url_multiple_slashes(self) -> None:
        """Test building URL with multiple slashes."""
        url = build_base_url("example.com//api//v1")
        assert url == "http://example.com//api//v1"

    def test_build_base_url_with_encoded_characters(self) -> None:
        """Test building URL with URL-encoded characters."""
        url = build_base_url("example.com/path%20with%20spaces")
        assert url == "http://example.com/path%20with%20spaces"


class TestBuildBaseUrlEdgeCases:
    """Test edge cases for build_base_url function."""

    def test_build_base_url_none_input(self) -> None:
        """Test building URL with None input."""
        with pytest.raises((TypeError, AttributeError)):
            build_base_url(None)

    def test_build_base_url_numeric_input(self) -> None:
        """Test building URL with numeric input."""
        with pytest.raises((TypeError, AttributeError)):
            build_base_url(12345)

    def test_build_base_url_list_input(self) -> None:
        """Test building URL with list input."""
        with pytest.raises((TypeError, AttributeError)):
            build_base_url(["example.com"])

    def test_build_base_url_only_protocol(self) -> None:
        """Test building URL with only protocol."""
        url = build_base_url("http://")
        assert url == "http://"

    def test_build_base_url_only_port(self) -> None:
        """Test building URL with only port."""
        url = build_base_url(":8080")
        assert url == "http://:8080"

    def test_build_base_url_malformed_url(self) -> None:
        """Test building URL with malformed input."""
        url = build_base_url("://example.com")
        # 假设函数会添加默认协议
        assert "example.com" in url

    def test_build_base_url_very_long_url(self) -> None:
        """Test building URL with very long domain."""
        long_domain = "a" * 253 + ".com"
        url = build_base_url(long_domain)
        assert url.startswith("http://")
        assert long_domain in url


class TestBuildBaseUrlIntegration:
    """Integration tests for build_base_url with real-world scenarios."""

    def test_build_base_url_qianfan_endpoint(self) -> None:
        """Test building URL for QianFan endpoint."""
        url = build_base_url("https://qianfan.baidubce.com")
        assert url == "https://qianfan.baidubce.com"

    def test_build_base_url_local_development(self) -> None:
        """Test building URL for local development."""
        url = build_base_url("localhost:8000")
        assert url == "http://localhost:8000"

    def test_build_base_url_internal_service(self) -> None:
        """Test building URL for internal service."""
        url = build_base_url("10.174.136.82:8691")
        assert url == "http://10.174.136.82:8691"

    def test_build_base_url_staging_environment(self) -> None:
        """Test building URL for staging environment."""
        url = build_base_url("https://staging-api.example.com:8443/v1")
        assert url == "https://staging-api.example.com:8443/v1"

    def test_build_base_url_with_api_path(self) -> None:
        """Test building URL with API path."""
        url = build_base_url("api.example.com/v2/embeddings")
        assert url == "http://api.example.com/v2/embeddings"

    def test_build_base_url_load_balancer(self) -> None:
        """Test building URL for load balancer."""
        url = build_base_url("lb.example.com:80")
        assert url == "http://lb.example.com:80"


class TestBuildBaseUrlWithMocking:
    """Test build_base_url with mocked dependencies."""

    def test_build_base_url_called_with_correct_params(self) -> None:
        """Test that build_base_url is called with correct parameters."""
        with mock.patch("databuilder_logic_sdk.utils.http_utils.build_base_url") as mock_build:
            mock_build.return_value = "http://example.com"

            result = mock_build("example.com")

            mock_build.assert_called_once_with("example.com")
            assert result == "http://example.com"

    def test_build_base_url_multiple_calls(self) -> None:
        """Test build_base_url with multiple calls."""
        endpoints = [
            "example1.com",
            "example2.com:8080",
            "https://example3.com",
        ]

        results = [build_base_url(ep) for ep in endpoints]

        assert results[0] == "http://example1.com"
        assert results[1] == "http://example2.com:8080"
        assert results[2] == "https://example3.com"


class TestBuildBaseUrlPerformance:
    """Performance tests for build_base_url."""

    def test_build_base_url_performance(self) -> None:
        """Test that build_base_url performs well with many calls."""
        import time

        start = time.time()
        for _ in range(10000):
            build_base_url("example.com")
        end = time.time()

        # 应该在 1 秒内完成
        assert (end - start) < 1.0

    def test_build_base_url_thread_safe(self) -> None:
        """Test that build_base_url is thread-safe."""
        import threading

        results = []

        def call_build_url() -> None:
            url = build_base_url("example.com")
            results.append(url)

        threads = [threading.Thread(target=call_build_url) for _ in range(100)]
        for t in threads:
            t.start()
        for t in threads:
            t.join()

        # 所有结果应该相同
        assert len(results) == 100
        assert all(r == "http://example.com" for r in results)


# 参数化测试
class TestBuildBaseUrlParametrized:
    """Parametrized tests for build_base_url."""

    @pytest.mark.parametrize(
        "input_url,expected",
        [
            ("example.com", "http://example.com"),
            ("http://example.com", "http://example.com"),
            ("https://example.com", "https://example.com"),
            ("example.com:8080", "http://example.com:8080"),
            ("192.168.1.1", "http://192.168.1.1"),
            ("localhost:3000", "http://localhost:3000"),
        ],
    )
    def test_build_base_url_common_cases(self, input_url: str, expected: str) -> None:
        """Test common URL building cases."""
        assert build_base_url(input_url) == expected

    @pytest.mark.parametrize("protocol", ["http://", "https://"])
    def test_build_base_url_preserves_protocols(self, protocol: str) -> None:
        """Test that all protocols are preserved."""
        url = build_base_url(f"{protocol}example.com")
        assert url.startswith(protocol)

    @pytest.mark.parametrize("port", ["80", "443", "8080", "8443", "3000", "5000"])
    def test_build_base_url_with_various_ports(self, port: str) -> None:
        """Test building URLs with various port numbers."""
        url = build_base_url(f"example.com:{port}")
        assert url == f"http://example.com:{port}"


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
