"""
Pattern Matcher for Permissions

Provides efficient wildcard pattern matching with caching.
"""

import fnmatch
import re
from functools import lru_cache
from typing import Pattern


class PatternMatcher:
    """
    Fast pattern matcher with wildcard support.

    Supports:
    - * (zero or more characters)
    - ? (exactly one character)
    - Case-sensitive matching by default
    - Compiled pattern caching for performance
    """

    def __init__(self):
        """Initialize pattern matcher with cache"""
        # Cache for compiled regex patterns
        self._regex_cache: dict[str, Pattern[str]] = {}

    def match(self, text: str, pattern: str, case_sensitive: bool = True) -> bool:
        """
        Match text against pattern with wildcards.

        Args:
            text: Text to match
            pattern: Pattern with wildcards (* and ?)
            case_sensitive: Whether matching is case-sensitive (default: True)

        Returns:
            True if text matches pattern

        Examples:
            >>> matcher = PatternMatcher()
            >>> matcher.match("git status", "git *")
            True
            >>> matcher.match("main.py", "*.py")
            True
            >>> matcher.match("test", "tes?")
            True
            >>> matcher.match("TEST", "test", case_sensitive=False)
            True
        """
        if not case_sensitive:
            text = text.lower()
            pattern = pattern.lower()

        # Use fnmatch for standard patterns (it's optimized in C)
        return fnmatch.fnmatch(text, pattern)

    def match_any(self, text: str, patterns: list[str], case_sensitive: bool = True) -> bool:
        """
        Check if text matches any of the given patterns.

        Args:
            text: Text to match
            patterns: List of patterns to check
            case_sensitive: Whether matching is case-sensitive (default: True)

        Returns:
            True if text matches any pattern

        Examples:
            >>> matcher = PatternMatcher()
            >>> matcher.match_any("main.py", ["*.py", "*.js"])
            True
            >>> matcher.match_any("test.txt", ["*.py", "*.js"])
            False
        """
        return any(self.match(text, pattern, case_sensitive) for pattern in patterns)

    def match_regex(self, text: str, pattern: str, case_sensitive: bool = True) -> bool:
        """
        Match text against regex pattern with caching.

        Args:
            text: Text to match
            pattern: Regex pattern
            case_sensitive: Whether matching is case-sensitive (default: True)

        Returns:
            True if text matches regex pattern
        """
        # Create cache key
        cache_key = f"{pattern}:{'cs' if case_sensitive else 'ci'}"

        # Get or compile pattern
        if cache_key not in self._regex_cache:
            flags = 0 if case_sensitive else re.IGNORECASE
            self._regex_cache[cache_key] = re.compile(pattern, flags)

        compiled_pattern = self._regex_cache[cache_key]
        return bool(compiled_pattern.match(text))

    def translate_to_regex(self, pattern: str) -> str:
        """
        Translate wildcard pattern to regex.

        Args:
            pattern: Wildcard pattern with * and ?

        Returns:
            Regex pattern string

        Examples:
            >>> matcher = PatternMatcher()
            >>> matcher.translate_to_regex("*.py")
            '.*\\\\.py'
            >>> matcher.translate_to_regex("test?")
            'test.'
        """
        return fnmatch.translate(pattern)

    def clear_cache(self) -> None:
        """Clear the regex pattern cache"""
        self._regex_cache.clear()


# Module-level singleton for convenience
_default_matcher = PatternMatcher()


def match(text: str, pattern: str, case_sensitive: bool = True) -> bool:
    """
    Convenience function for pattern matching.

    Args:
        text: Text to match
        pattern: Pattern with wildcards (* and ?)
        case_sensitive: Whether matching is case-sensitive (default: True)

    Returns:
        True if text matches pattern

    Examples:
        >>> match("git status", "git *")
        True
        >>> match("main.py", "*.py")
        True
        >>> match("test", "tes?")
        True
    """
    return _default_matcher.match(text, pattern, case_sensitive)


def match_any(text: str, patterns: list[str], case_sensitive: bool = True) -> bool:
    """
    Convenience function for matching against multiple patterns.

    Args:
        text: Text to match
        patterns: List of patterns to check
        case_sensitive: Whether matching is case-sensitive (default: True)

    Returns:
        True if text matches any pattern

    Examples:
        >>> match_any("main.py", ["*.py", "*.js"])
        True
        >>> match_any("test.txt", ["*.py", "*.js"])
        False
    """
    return _default_matcher.match_any(text, patterns, case_sensitive)
