"""
Text pattern matching strategies for message analysis.
Handles keyword detection and pattern matching.
Follows the Strategy pattern and Single Responsibility Principle.
"""
from abc import ABC, abstractmethod
from typing import List


def _normalize_case_insensitive(text: str) -> str:
    if text is None:
        return ""
    return str(text).lower()


def _normalize_whitespace(text: str) -> str:
    if text is None:
        return ""
    return " ".join(str(text).split())


class PatternMatchingStrategy(ABC):
    """Abstract base class for pattern matching strategies."""
    
    @abstractmethod
    def matches(self, text: str) -> bool:
        """Check if text matches the pattern.
        
        Args:
            text: The text to check
            
        Returns:
            True if text matches the pattern
        """
        pass


class KeywordMatchingStrategy(PatternMatchingStrategy):
    """Matches text against a list of keywords."""
    
    def __init__(self, keywords: List[str], case_sensitive: bool = False):
        """Initialize the keyword matching strategy.
        
        Args:
            keywords: List of keywords to match
            case_sensitive: Whether matching should be case-sensitive
        """
        self._keywords = keywords
        self._case_sensitive = case_sensitive
    
    def matches(self, text: str) -> bool:
        """Check if text contains any of the keywords.
        
        Args:
            text: The text to check
            
        Returns:
            True if any keyword is found in text
        """
        if not text:
            return False
        
        if self._case_sensitive:
            return any(keyword in text for keyword in self._keywords)
        else:
            text_lower = _normalize_case_insensitive(text)
            return any(_normalize_case_insensitive(keyword) in text_lower 
                      for keyword in self._keywords)


class MultiPatternMatchingStrategy(PatternMatchingStrategy):
    """Matches text against multiple pattern phrases."""
    
    def __init__(self, patterns: List[str]):
        """Initialize with multiple patterns.
        
        Args:
            patterns: List of pattern strings to match
        """
        self._patterns = patterns
    
    def matches(self, text: str) -> bool:
        """Check if text contains any of the patterns.
        
        Args:
            text: The text to check
            
        Returns:
            True if any pattern is found in text
        """
        if not text:
            return False
        
        text_lower = _normalize_case_insensitive(text)
        return any(_normalize_case_insensitive(pattern) in text_lower 
                  for pattern in self._patterns)


class ConfirmationDetectionStrategy(PatternMatchingStrategy):
    """Detects if text is a confirmation phrase."""
    
    CONFIRMATION_WORDS = ['yes', 'sure', 'of course', 'no']
    
    def matches(self, text: str) -> bool:
        """Check if text is a confirmation phrase.
        
        Args:
            text: The text to check
            
        Returns:
            True if text contains confirmation words
        """
        strategy = KeywordMatchingStrategy(self.CONFIRMATION_WORDS)
        return strategy.matches(text)


class PatternMatcher:
    """
    Context class that uses a pattern matching strategy.
    Follows the Strategy pattern for flexible pattern detection.
    """
    
    def __init__(self, strategy: PatternMatchingStrategy):
        """Initialize the pattern matcher with a specific strategy.
        
        Args:
            strategy: The pattern matching strategy to use
        """
        self._strategy = strategy
    
    def matches(self, text: str) -> bool:
        """Check if text matches the pattern using the configured strategy.
        
        Args:
            text: The text to check
            
        Returns:
            True if text matches the pattern
        """
        return self._strategy.matches(text)
    
    def set_strategy(self, strategy: PatternMatchingStrategy):
        """Change the pattern matching strategy.
        
        Args:
            strategy: The new pattern matching strategy to use
        """
        self._strategy = strategy


def is_confirmation(text: str) -> bool:
    """Check if text is a confirmation phrase.
    
    Args:
        text: The text to check
        
    Returns:
            True if text is a confirmation
    """
    strategy = ConfirmationDetectionStrategy()
    return strategy.matches(text)


def contains_keywords(text: str, keywords: List[str], case_sensitive: bool = False) -> bool:
    """Check if text contains any of the specified keywords.
    
    Args:
        text: The text to check
        keywords: List of keywords to search for
        case_sensitive: Whether matching should be case-sensitive
        
    Returns:
        True if any keyword is found
    """
    strategy = KeywordMatchingStrategy(keywords, case_sensitive)
    return strategy.matches(text)


