"""
API Compatibility Tests for Kakashi.

These tests ensure all Kakashi APIs work correctly and
maintain backward compatibility.
"""

import pytest
import sys
import traceback
from pathlib import Path
from typing import Any
import tempfile

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))

class TestBasicLogging:
    """Test basic logging functionality."""
    
    def test_basic_imports(self):
        """Test that all basic imports work."""
        from kakashi import get_logger, get_async_logger
        from kakashi.core import Logger, AsyncLogger, LogLevel
        from kakashi.core.records import LogRecord, LogContext
        
        assert get_logger is not None
        assert get_async_logger is not None
        assert Logger is not None
        assert AsyncLogger is not None
        assert LogLevel is not None
        assert LogRecord is not None
        assert LogContext is not None
    
    def test_sync_logger_creation(self, kakashi_sync_logger):
        """Test sync logger creation and basic operations."""
        logger = kakashi_sync_logger
        assert logger is not None
        assert hasattr(logger, 'info')
        assert hasattr(logger, 'warning')
        assert hasattr(logger, 'error')
        assert hasattr(logger, 'debug')
        assert hasattr(logger, 'critical')
    
    def test_async_logger_creation(self, kakashi_async_logger):
        """Test async logger creation and basic operations."""
        logger = kakashi_async_logger
        assert logger is not None
        assert hasattr(logger, 'info')
        assert hasattr(logger, 'warning')
        assert hasattr(logger, 'error')
        assert hasattr(logger, 'debug')
        assert hasattr(logger, 'critical')
    
    def test_basic_logging_operations(self, kakashi_sync_logger):
        """Test that basic logging operations work without errors."""
        logger = kakashi_sync_logger
        
        # Test all log levels
        logger.debug("Debug message")
        logger.info("Info message")
        logger.warning("Warning message")
        logger.error("Error message")
        logger.critical("Critical message")
        
        # Test with fields
        logger.info("Message with fields", user_id=123, action="test")
    
    def test_structured_logging(self, kakashi_structured_logger):
        """Test structured logging functionality."""
        logger = kakashi_structured_logger
        assert logger is not None
        
        # Test structured logging with fields
        logger.info("Structured message", user_id=123, action="test")
        
        # Test specialized structured logging methods
        logger.metric("test_metric", 42.5, unit="count")
        logger.counter("test_counter", 1)
        logger.timer("test_operation", 15.5, unit="ms")
        
        # Verify the specialized methods exist
        assert hasattr(logger, 'metric')
        assert hasattr(logger, 'counter')
        assert hasattr(logger, 'timer')

class TestConfiguration:
    """Test configuration system."""
    
    def test_log_level_validation(self):
        """Test log level validation and conversion."""
        from kakashi.core import LogLevel
        
        # Test string to LogLevel conversion
        assert LogLevel.from_name("DEBUG") == LogLevel.DEBUG
        assert LogLevel.from_name("INFO") == LogLevel.INFO
        assert LogLevel.from_name("WARNING") == LogLevel.WARNING
        assert LogLevel.from_name("ERROR") == LogLevel.ERROR
        assert LogLevel.from_name("CRITICAL") == LogLevel.CRITICAL
        
        # Test integer to LogLevel conversion
        assert LogLevel(10) == LogLevel.DEBUG
        assert LogLevel(20) == LogLevel.INFO
        assert LogLevel(30) == LogLevel.WARNING
        assert LogLevel(40) == LogLevel.ERROR
        assert LogLevel(50) == LogLevel.CRITICAL
        
        # Test invalid log level handling
        with pytest.raises(KeyError):
            LogLevel.from_name("INVALID")

class TestContextManagement:
    """Test context management functionality."""
    
    def test_context_creation(self):
        """Test LogContext creation and usage."""
        from kakashi.core.records import LogContext
        
        # Test creating context with various fields
        context = LogContext(
            ip="127.0.0.1",
            user_id="test-user",
            service_name="test-service"
        )
        
        assert context.ip == "127.0.0.1"
        assert context.user_id == "test-user"
        assert context.service_name == "test-service"
    
    def test_context_merging(self):
        """Test context merging functionality."""
        from kakashi.core.records import LogContext
        
        context1 = LogContext(ip="127.0.0.1", user_id="user1")
        context2 = LogContext(user_id="user2", service_name="service1")
        
        merged = context1.merge(context2)
        
        # user_id should be from context2 (other takes precedence)
        assert merged.user_id == "user2"
        # ip should be from context1 (only in context1)
        assert merged.ip == "127.0.0.1"
        # service_name should be from context2 (only in context2)
        assert merged.service_name == "service1"

class TestPipelineSystem:
    """Test pipeline system functionality."""
    
    def test_log_record_creation(self):
        """Test LogRecord creation with proper parameters."""
        from kakashi.core.records import LogRecord, LogLevel, LogContext
        import time
        
        # Create a test record with all required parameters
        context = LogContext(user_id="test-user")
        record = LogRecord(
            timestamp=time.time(),
            level=LogLevel.INFO,
            logger_name="test_logger",
            message="Test message",
            context=context
        )
        
        assert record.level == LogLevel.INFO
        assert record.logger_name == "test_logger"
        assert record.message == "Test message"
        assert record.context == context
    
    def test_log_record_with_fields(self):
        """Test LogRecord with structured fields."""
        from kakashi.core.records import LogRecord, LogLevel
        import time
        
        fields = {"user_id": 123, "action": "test"}
        record = LogRecord(
            timestamp=time.time(),
            level=LogLevel.INFO,
            logger_name="test_logger",
            message="Test message",
            fields=fields
        )
        
        assert record.fields == fields
        assert record.fields["user_id"] == 123
        assert record.fields["action"] == "test"

class TestErrorHandling:
    """Test error handling and edge cases."""
    
    def test_invalid_log_levels(self):
        """Test handling of invalid log levels."""
        from kakashi.core import LogLevel
        
        # Test invalid string
        with pytest.raises(KeyError):
            LogLevel.from_name("INVALID")
        
        # Test invalid integer
        with pytest.raises(ValueError):
            LogLevel(999)
    
    def test_malformed_messages(self):
        """Test handling of malformed messages."""
        logger = pytest.importorskip("kakashi").get_logger("test_malformed")
        
        # Test None message - should handle gracefully
        try:
            logger.info(None)
        except Exception:
            # If it throws an exception, that's OK as long as it doesn't crash
            pass
        
        # Test empty message
        logger.info("")
        
        # Test very long message
        long_message = "x" * 10000
        logger.info(long_message)
    
    def test_concurrent_access(self):
        """Test concurrent access to loggers."""
        import threading
        import time
        
        logger = pytest.importorskip("kakashi").get_logger("test_concurrent")
        
        def log_messages():
            for i in range(100):
                logger.info(f"Message {i} from thread {threading.current_thread().name}")
                time.sleep(0.001)
        
        threads = []
        for i in range(5):
            thread = threading.Thread(target=log_messages, name=f"Thread-{i}")
            threads.append(thread)
            thread.start()
        
        for thread in threads:
            thread.join()
        
        # If we get here without errors, concurrent access works
        assert True
