"""Filtering utilities for event aggregation."""

import shlex
from pathlib import PurePosixPath, PureWindowsPath

# ---------------------------------------------------------------------------
# Binary-name patterns that indicate noise, not a real OpenClaw detection.
# These are checked against the *extracted binary name* (lowercased, no ext).
# ---------------------------------------------------------------------------

# Substring patterns -- matched anywhere in the binary name (case-insensitive).
# Broad enough to catch variants like "Google Chrome" matching "chrome".
_FILTERED_PATTERNS = frozenset([
    # Browsers
    "chrome", "msedge", "firefox", "brave", "opera", "iexplore", "island",
    "safari",
    # Editors / IDEs
    "notepad", "textedit", "sublime", "vscode", "code",
    # Self-detection (our own discovery tool)
    "astrix-",
    # Office / document viewers
    "winword", "excel", "powerpnt", "outlook", "onenote", "msaccess", "mspub",
    "acrord32", "acrobat",
    "preview", "pages", "numbers", "keynote",
    # Other
    "tmux", "become-success", "remediations",
])

# Exact binary names -- too short for safe substring matching.
_FILTERED_EXACT = frozenset([
    "ls", "find", "grep",
])


# ---------------------------------------------------------------------------
# Binary extraction helpers
# ---------------------------------------------------------------------------

def extract_binary_name(path_or_filename: str | None, *, is_windows: bool = False) -> str:
    """Extract and normalize binary name from a file path or filename.

    Uses ``PureWindowsPath`` or ``PurePosixPath`` based on the OS hint so
    that Windows back-slash paths are parsed correctly even on a Unix host.

    Args:
        path_or_filename: A file path or bare filename (may be ``None``).
        is_windows: When ``True`` use ``PureWindowsPath``, otherwise ``PurePosixPath``.

    Returns:
        Lowercased binary stem (extension stripped), or ``""`` if input is empty.
    """
    if not path_or_filename:
        return ""
    path_cls = PureWindowsPath if is_windows else PurePosixPath
    return path_cls(path_or_filename.strip()).stem.lower()


def extract_binary_from_commandline(cmdline: str | None) -> str:
    """Extract the raw executable token from a commandline string.

    Uses :func:`shlex.split` to properly handle quoted paths and whitespace.
    Exceptions are **not** caught here -- the caller is expected to handle
    them (e.g. the aggregator's per-entry ``try/except``).

    Args:
        cmdline: Full commandline string (may be ``None``).

    Returns:
        The first token (executable path/filename), or ``""`` if input is empty.
    """
    if not cmdline:
        return ""
    cmdline = cmdline.strip()
    if not cmdline:
        return ""
    tokens = shlex.split(cmdline)
    if not tokens:
        return ""
    return tokens[0]


# ---------------------------------------------------------------------------
# Filter decision
# ---------------------------------------------------------------------------

def is_filtered_binary(binary_name: str) -> bool:
    """Check whether an extracted binary name should be filtered out.

    Filters browsers, utilities, and known false positives.

    Args:
        binary_name: Lowercased binary stem (output of :func:`extract_binary_name`).

    Returns:
        ``True`` if the event should be filtered out (noise).
    """
    if not binary_name:
        return False

    # Exact match for short names
    if binary_name in _FILTERED_EXACT:
        return True

    # Substring match for longer / composite names
    for pattern in _FILTERED_PATTERNS:
        if pattern in binary_name:
            return True

    return False
