"""
Фильтры для мультибот маршрутизации и A/B тестирования.

BotIncludeFilter — пропускает только указанного бота.
BotExcludeFilter — пропускает всех, кроме заблокированных ботов (мутабельный set).
ABGroupFilter — пропускает пользователя, попавшего в определённую группу A/B теста.
"""

from collections.abc import Awaitable, Callable

from aiogram.filters import BaseFilter
from aiogram.types import CallbackQuery, Message, TelegramObject


class BotIncludeFilter(BaseFilter):
    """Пропускает обновления только от указанного бота."""

    def __init__(self, bot_id: int) -> None:
        self.bot_id = bot_id

    async def __call__(self, event: TelegramObject) -> bool:
        bot = event.bot  # type: ignore[union-attr]
        return bot.id == self.bot_id


class BotExcludeFilter(BaseFilter):
    """Пропускает обновления от всех ботов, кроме заблокированных.

    blocked_bot_ids — мутабельный set, shared by reference.
    Добавление bot_id в set автоматически исключает бота из default роутера.
    """

    def __init__(self, blocked_bot_ids: set[int] | None = None) -> None:
        self.blocked_bot_ids: set[int] = blocked_bot_ids if blocked_bot_ids is not None else set()

    async def __call__(self, event: TelegramObject) -> bool:
        bot = event.bot  # type: ignore[union-attr]
        return bot.id not in self.blocked_bot_ids


class ABGroupFilter(BaseFilter):
    """Пропускает пользователя, если resolver возвращает совпадающую группу.

    resolver: (bot_id, user_id) -> group_name (async)
    """

    def __init__(self, group_name: str, resolver: Callable[[int, int], Awaitable[str]]) -> None:
        self.group_name = group_name
        self.resolver = resolver

    async def __call__(self, event: Message | CallbackQuery) -> bool:
        bot = event.bot  # type: ignore[union-attr]
        user = event.from_user
        if user is None:
            return False
        resolved = await self.resolver(bot.id, user.id)
        return resolved == self.group_name


__all__ = [
    "ABGroupFilter",
    "BotExcludeFilter",
    "BotIncludeFilter",
]
