"""Text matching with word-boundary default and /regex/ syntax."""

from __future__ import annotations

import re


def parse_query(query: str) -> re.Pattern[str]:
    """Parse a search query into a compiled regex.

    Plain text queries use word-boundary matching (case-insensitive).
    Queries wrapped in /slashes/ are treated as regex.
    An ``i`` flag after the closing slash enables case-insensitive regex.

    Examples::

        parse_query("SAM")        # matches "SAM" but not "SAME"
        parse_query("/SAM/")      # regex, case-sensitive
        parse_query("/SAM/i")     # regex, case-insensitive
    """
    if not query:
        return re.compile("")

    m = re.fullmatch(r"/(.+)/([i]?)", query)
    if m:
        pattern, flags_str = m.group(1), m.group(2)
        flags = re.IGNORECASE if "i" in flags_str else 0
        try:
            return re.compile(pattern, flags)
        except re.error as exc:
            raise ValueError(f"Invalid regex: {exc}") from exc

    # Default: word-boundary, case-insensitive
    # Only use \b where the query edge is a word character (letter/digit/_),
    # since \b requires a word/non-word transition.
    escaped = re.escape(query)
    prefix = r"\b" if re.match(r"\w", query) else ""
    suffix = r"\b" if re.match(r"\w", query[-1]) else ""
    return re.compile(rf"{prefix}{escaped}{suffix}", re.IGNORECASE)


def text_match(query: str, *fields: str) -> bool:
    """Return True if *query* matches any of the given text fields."""
    pattern = parse_query(query)
    return any(pattern.search(field) for field in fields)
