"""
Comparison strategies for different types of text comparisons.
Follows the Strategy pattern and Single Responsibility Principle.
"""
from abc import ABC, abstractmethod
from typing import Any


def _normalize_for_comparison(value: Any) -> str:
    if value is None:
        return ""
    return str(value).strip().lower()


class ComparisonStrategy(ABC):
    """Abstract base class for comparison strategies."""
    
    @abstractmethod
    def compare(self, value1: Any, value2: Any) -> bool:
        """Compare two values according to the specific strategy.
        
        Args:
            value1: First value to compare
            value2: Second value to compare
            
        Returns:
            True if values match according to the strategy, False otherwise
        """
        pass


class ExactComparisonStrategy(ComparisonStrategy):
    """Compares values exactly after normalization."""
    
    def compare(self, value1: Any, value2: Any) -> bool:
        """Compare two values for exact equality after normalization.
        
        Args:
            value1: First value to compare
            value2: Second value to compare
            
        Returns:
            True if normalized values are exactly equal
        """
        return _normalize_for_comparison(value1) == _normalize_for_comparison(value2)


class ContainsComparisonStrategy(ComparisonStrategy):
    """Checks if one value contains another after normalization."""
    
    def compare(self, value1: Any, value2: Any) -> bool:
        """Check if value1 contains value2 after normalization.
        
        Args:
            value1: The container value
            value2: The value to search for
            
        Returns:
            True if normalized value1 contains normalized value2
        """
        norm1 = _normalize_for_comparison(value1)
        norm2 = _normalize_for_comparison(value2)
        return norm2 in norm1


class BidirectionalContainsStrategy(ComparisonStrategy):
    """Checks if either value contains the other after normalization."""
    
    def compare(self, value1: Any, value2: Any) -> bool:
        """Check if either value contains the other after normalization.
        
        Args:
            value1: First value
            value2: Second value
            
        Returns:
            True if value1 contains value2 OR value2 contains value1
        """
        norm1 = _normalize_for_comparison(value1)
        norm2 = _normalize_for_comparison(value2)
        return norm2 in norm1 or norm1 in norm2


class TextComparator:
    """
    Context class that uses a comparison strategy.
    Follows the Strategy pattern for flexible comparison behavior.
    """
    
    def __init__(self, strategy: ComparisonStrategy):
        """Initialize the comparator with a specific strategy.
        
        Args:
            strategy: The comparison strategy to use
        """
        self._strategy = strategy
    
    def compare(self, value1: Any, value2: Any) -> bool:
        """Compare two values using the configured strategy.
        
        Args:
            value1: First value to compare
            value2: Second value to compare
            
        Returns:
            Comparison result according to the strategy
        """
        return self._strategy.compare(value1, value2)
    
    def set_strategy(self, strategy: ComparisonStrategy):
        """Change the comparison strategy.
        
        Args:
            strategy: The new comparison strategy to use
        """
        self._strategy = strategy


# Convenience functions for common comparison operations
def are_equal_normalized(value1: Any, value2: Any) -> bool:
    """
    Check if two values are equal after normalization.
    
    Args:
        value1: First value
        value2: Second value
        
    Returns:
        True if values are equal after normalization
    """
    strategy = ExactComparisonStrategy()
    return strategy.compare(value1, value2)


def contains_normalized(container: Any, value: Any) -> bool:
    """
    Check if container contains value after normalization.
    
    Args:
        container: The container value
        value: The value to search for
        
    Returns:
        True if container contains value after normalization
    """
    strategy = ContainsComparisonStrategy()
    return strategy.compare(container, value)


def either_contains_normalized(value1: Any, value2: Any) -> bool:
    """
    Check if either value contains the other after normalization.
    
    Args:
        value1: First value
        value2: Second value
        
    Returns:
        True if either value contains the other
    """
    strategy = BidirectionalContainsStrategy()
    return strategy.compare(value1, value2)
