"""
Integration tests for the Kindred AI SDK.
"""

import unittest
from kindred_ai import Interceptor
from kindred_ai.rules import _rewrite_url, validate_rules


class TestURLRewriting(unittest.TestCase):
    """Test URL rewriting logic."""
    
    def test_simple_rewrite(self):
        """Test simple hostname replacement."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        original = "https://api.openai.com/v1/chat/completions"
        expected = "https://my-gateway.com/openai/v1/chat/completions"
        result = _rewrite_url(original, rules)
        self.assertEqual(result, expected)
    
    def test_rewrite_with_query_params(self):
        """Test URL rewriting preserves query parameters."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        original = "https://api.openai.com/v1/models?limit=10&offset=0"
        expected = "https://my-gateway.com/openai/v1/models?limit=10&offset=0"
        result = _rewrite_url(original, rules)
        self.assertEqual(result, expected)
    
    def test_rewrite_with_path_in_destination(self):
        """Test URL rewriting when destination has a path."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        original = "https://api.openai.com/v1/models"
        expected = "https://my-gateway.com/openai/v1/models"
        result = _rewrite_url(original, rules)
        self.assertEqual(result, expected)
    
    def test_no_match_returns_original(self):
        """Test that unmatched URLs are returned unchanged."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        original = "https://api.github.com/users"
        result = _rewrite_url(original, rules)
        self.assertEqual(result, original)
    
    def test_empty_rules(self):
        """Test that empty rules return original URL."""
        rules = {}
        original = "https://api.openai.com/v1/models"
        result = _rewrite_url(original, rules)
        self.assertEqual(result, original)


class TestRulesValidation(unittest.TestCase):
    """Test rules validation."""
    
    def test_valid_rules(self):
        """Test that valid rules pass validation."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai",
            "api.stripe.com": "http://localhost:8080/stripe"
        }
        # Should not raise
        validate_rules(rules)
    
    def test_invalid_rules_not_dict(self):
        """Test that non-dict rules raise ValueError."""
        with self.assertRaises(ValueError):
            validate_rules("not a dict")
    
    def test_invalid_rules_empty_hostname(self):
        """Test that empty hostname raises ValueError."""
        with self.assertRaises(ValueError):
            validate_rules({"": "https://example.com"})
    
    def test_invalid_rules_empty_destination(self):
        """Test that empty destination raises ValueError."""
        with self.assertRaises(ValueError):
            validate_rules({"api.openai.com": ""})
    
    def test_invalid_rules_no_netloc(self):
        """Test that destination without hostname raises ValueError."""
        with self.assertRaises(ValueError):
            validate_rules({"api.openai.com": "/relative/path"})


class TestInterceptorLifecycle(unittest.TestCase):
    """Test interceptor initialization and lifecycle."""
    
    def setUp(self):
        """Set up test fixtures."""
        if Interceptor.is_active():
            Interceptor.stop()
    
    def tearDown(self):
        """Clean up after tests."""
        if Interceptor.is_active():
            Interceptor.stop()
    
    def test_init_and_stop(self):
        """Test basic initialization and stopping."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        self.assertFalse(Interceptor.is_active())
        Interceptor.init(routing_rules=rules, verbose=False)
        self.assertTrue(Interceptor.is_active())
        self.assertEqual(Interceptor.get_rules(), rules)
        
        Interceptor.stop()
        self.assertFalse(Interceptor.is_active())
    
    def test_double_init_warning(self):
        """Test that double initialization logs a warning."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        Interceptor.init(routing_rules=rules, verbose=False)
        # Should not raise, but should log warning
        Interceptor.init(routing_rules=rules, verbose=False)
        Interceptor.stop()
    
    def test_context_manager(self):
        """Test context manager usage."""
        rules = {
            "api.openai.com": "https://my-gateway.com/openai"
        }
        
        self.assertFalse(Interceptor.is_active())
        
        with Interceptor.scope(routing_rules=rules, verbose=False):
            self.assertTrue(Interceptor.is_active())
            self.assertEqual(Interceptor.get_rules(), rules)
        
        self.assertFalse(Interceptor.is_active())


class TestCatchAllRouting(unittest.TestCase):
    """Test catch-all routing functionality using explicit rules."""
    
    def test_catch_all_with_star(self):
        """Test catch-all routing using '*' key."""
        rules = {
            "*": "http://localhost:8080/proxy"
        }
        
        # Test that any URL gets rewritten
        test_urls = [
            "https://api.stripe.com/v1/charges",
            "https://api.openai.com/v1/models",
            "https://api.github.com/users"
        ]
        
        for url in test_urls:
            result = _rewrite_url(url, rules)
            self.assertTrue(result.startswith("http://localhost:8080/proxy"))
    
    def test_specific_rule_overrides_catch_all(self):
        """Test that specific rules take precedence over catch-all."""
        rules = {
            "*": "http://localhost:8080/proxy",
            "api.stripe.com": "http://localhost:8080/stripe-specific"
        }
        
        # Specific rule should match
        result = _rewrite_url("https://api.stripe.com/v1/charges", rules)
        self.assertEqual(result, "http://localhost:8080/stripe-specific/v1/charges")
        
        # Catch-all should match others
        result = _rewrite_url("https://api.openai.com/v1/models", rules)
        self.assertTrue(result.startswith("http://localhost:8080/proxy"))


if __name__ == '__main__':
    unittest.main()

