import logging


class LogRecordSanitizerFilter(logging.Filter):
    """
    Removes request/response objects from log records before OTLP export.
    OpenTelemetry attributes must be primitive types (bool, str, int, float, bytes).
    Django's request_logging adds Response/HttpRequest objects which cause:
    "Invalid type Response for attribute 'response' value"
    """

    def filter(self, record: logging.LogRecord) -> bool:
        # Remove non-serializable attributes (keep response_status, response_str, etc.)
        for attr in ("request", "response"):
            if hasattr(record, attr):
                try:
                    delattr(record, attr)
                except Exception:
                    pass
        return True


class HealthCheckFilter(logging.Filter):
    """Drops log records for health check endpoints to reduce noise."""

    HEALTH_CHECK_PATHS = [
        "/health_check",
        "/healthcheck",
        "/health",
        "/ping",
    ]

    # Function names that are health check handlers
    HEALTH_CHECK_FUNC_NAMES = {
        "health_check",
        "healthcheck",
        "health",
        "ping",
    }

    # Case-insensitive substrings that indicate a health check log body
    HEALTH_CHECK_MSG_KEYWORDS = [
        "health check endpoint",
        "health_check endpoint",
        "healthcheck endpoint",
        "health check called",
        "health_check called",
    ]

    def filter(self, record: logging.LogRecord) -> bool:
        # Drop logs emitted from health check handler functions
        if getattr(record, "funcName", "") in self.HEALTH_CHECK_FUNC_NAMES:
            return False

        msg = record.getMessage()

        # Drop logs that contain a health check URL path
        for path in self.HEALTH_CHECK_PATHS:
            if path in msg:
                return False

        # Drop logs whose message body describes a health check call
        msg_lower = msg.lower()
        for keyword in self.HEALTH_CHECK_MSG_KEYWORDS:
            if keyword in msg_lower:
                return False

        return True


class NoisyLoggerFilter(logging.Filter):
    NOISY_LOGGERS = [
        "urllib3",
        "urllib3.connectionpool",
        "opentelemetry",
        "opentelemetry.sdk",
        "opentelemetry.exporter",
        "requests",
        "requests.packages.urllib3",
        "httpx",
        "botocore",
        "boto3",
    ]

    def filter(self, record):
        for noisy in self.NOISY_LOGGERS:
            if record.name.startswith(noisy):
                return False
        return True
