"""Custom log filters."""

import logging
import re
from typing import List, Pattern


class SensitiveDataFilter(logging.Filter):
    """Filter to redact sensitive data from logs."""

    # Patterns for sensitive data
    SENSITIVE_PATTERNS: List[Pattern] = [
        re.compile(r"(?i)(api[_-]?key|apikey)\s*[:=]\s*['\"]?([a-zA-Z0-9_-]{10,})['\"]?", re.IGNORECASE),
        re.compile(r"(?i)(token)\s*[:=]\s*['\"]?([a-zA-Z0-9_-]{20,})['\"]?", re.IGNORECASE),
        re.compile(r"(?i)(password|passwd|pwd)\s*[:=]\s*['\"]?([^\s'\"\n]{3,})['\"]?", re.IGNORECASE),
        re.compile(r"(?i)(secret)\s*[:=]\s*['\"]?([a-zA-Z0-9_-]{10,})['\"]?", re.IGNORECASE),
        re.compile(r"postgresql://[^:]+:([^@]+)@", re.IGNORECASE),
        re.compile(r"sqlite:///([^\s]+)", re.IGNORECASE),
    ]

    # Fields that should be redacted
    SENSITIVE_FIELDS: List[str] = [
        "api_key",
        "api_token",
        "bot_token",
        "password",
        "secret",
        "database_url",
        "telegram_bot_token",
        "slack_webhook_url",
    ]

    def filter(self, record: logging.LogRecord) -> bool:
        """
        Filter log record and redact sensitive data.

        Args:
            record: Log record to filter

        Returns:
            True (always passes, but modifies record)
        """
        # Redact sensitive patterns in message
        if hasattr(record, "msg") and isinstance(record.msg, str):
            record.msg = self._redact_string(record.msg)

        # Redact sensitive fields in extra data
        if hasattr(record, "extra_fields"):
            for field in self.SENSITIVE_FIELDS:
                if field in record.extra_fields:
                    record.extra_fields[field] = "[REDACTED]"

        return True

    def _redact_string(self, text: str) -> str:
        """
        Redact sensitive patterns in string.

        Args:
            text: Text to redact

        Returns:
            Redacted text
        """
        result = text
        for pattern in self.SENSITIVE_PATTERNS:
            result = pattern.sub(r"\1=[REDACTED]", result)
        return result


class RateLimitFilter(logging.Filter):
    """Filter to rate limit repeated log messages."""

    def __init__(self, max_repeats: int = 5, window_seconds: int = 60):
        """
        Initialize rate limit filter.

        Args:
            max_repeats: Maximum number of identical messages in window
            window_seconds: Time window in seconds
        """
        super().__init__()
        self.max_repeats = max_repeats
        self.window_seconds = window_seconds
        self.message_counts: dict = {}

    def filter(self, record: logging.LogRecord) -> bool:
        """
        Filter log record based on rate limiting.

        Args:
            record: Log record to filter

        Returns:
            True if message should be logged, False otherwise
        """
        import time

        message_key = f"{record.levelname}:{record.getMessage()}"
        current_time = time.time()

        # Clean old entries
        self.message_counts = {
            k: v
            for k, v in self.message_counts.items()
            if current_time - v["first_seen"] < self.window_seconds
        }

        # Check rate limit
        if message_key in self.message_counts:
            count = self.message_counts[message_key]["count"]
            if count >= self.max_repeats:
                return False
            self.message_counts[message_key]["count"] += 1
        else:
            self.message_counts[message_key] = {"count": 1, "first_seen": current_time}

        return True

