from logging import Filter
from typing import TYPE_CHECKING, Optional
import warnings

try:
    from finalsa.traceability.context import (
        get_correlation_id,
        get_span_id,
        get_trace_id
    )
    TRACEABILITY_AVAILABLE = True
except ImportError:
    TRACEABILITY_AVAILABLE = False
    
    def get_correlation_id():
        return None
    
    def get_span_id():
        return None
        
    def get_trace_id():
        return None

if TYPE_CHECKING:
    from logging import LogRecord


class CorrelationIdFilter(Filter):
    """Logging filter to attach correlation IDs to log records.
    
    This filter automatically adds correlation_id, trace_id, and span_id
    to log records using the finalsa-traceability context. If the traceability
    package is not available, the IDs will be set to None.
    
    Args:
        name: Filter name (inherited from logging.Filter)
        uuid_length: Optional length for UUID truncation (currently unused)
        default_value: Default value when traceability is unavailable (currently unused)
    """

    def __init__(self, name: str = '', uuid_length: Optional[int] = None, default_value: Optional[str] = None):
        super().__init__(name=name)
        self.uuid_length = uuid_length
        self.default_value = default_value
        
        if not TRACEABILITY_AVAILABLE:
            # Log warning once when filter is created
            warnings.warn(
                "finalsa-traceability not available. Correlation IDs will be None. "
                "Install finalsa-traceability for full functionality."
            )

    def filter(self, record: 'LogRecord') -> bool:
        """Add correlation IDs to the log record.
        
        Args:
            record: The log record to enhance
            
        Returns:
            Always True (never filters out records)
        """
        try:
            record.correlation_id = get_correlation_id()
            record.trace_id = get_trace_id()
            record.span_id = get_span_id()
        except Exception as e:
            # Graceful degradation - don't break logging if traceability fails
            warnings.warn(f"Failed to get traceability context: {e}")
            record.correlation_id = self.default_value
            record.trace_id = None
            record.span_id = None
        
        return True
