import re
from typing import Callable, List, Union, Any

class Filter:
    """Zehnex Filter System."""

    @staticmethod
    def command(cmds: Union[str, List[str]]) -> Callable:
        """Command filter (e.g. /start)."""
        if isinstance(cmds, str): cmds = [cmds]
        cmds = [c.lower() for c in cmds]
        def check(ctx):
            if not ctx.text or not ctx.text.startswith("/"): return False
            cmd = ctx.text[1:].split()[0].lower().split("@")[0]
            return cmd in cmds
        return check

    @staticmethod
    def text(value: str) -> Callable:
        def check(ctx):
            return ctx.text == value
        return check

    @staticmethod
    def regex(pattern: str) -> Callable:
        compiled = re.compile(pattern)
        def check(ctx):
            return bool(compiled.search(ctx.text or ""))
        return check

    @staticmethod
    def is_url(ctx) -> bool:
        return bool(re.search(r'https?://[^\s]+', ctx.text or ""))

    @staticmethod
    def AND(*filters) -> Callable:
        def check(ctx):
            return all((f(ctx) if callable(f) else False) for f in filters)
        return check

    @staticmethod
    def NOT(f) -> Callable:
        def check(ctx):
            return not (f(ctx) if callable(f) else False)
        return check

class Router:
    """Router for grouping handlers."""
    def __init__(self):
        self._handlers = []

    def message(self, *filters, commands=None):
        def decorator(func):
            self._handlers.append(("message", func, filters, commands))
            return func
        return decorator

    def include_in(self, bot):
        for update_type, func, filters, commands in self._handlers:
            if update_type == "message":
                bot.message(*filters, commands=commands)(func)
