"""Тесты для BotIncludeFilter, BotExcludeFilter, ABGroupFilter."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from ui_router.aiogram.filters import ABGroupFilter, BotExcludeFilter, BotIncludeFilter


def _make_event(bot_id: int, user_id: int = 1) -> MagicMock:
    """Создать mock-событие с bot.id и from_user.id."""
    event = MagicMock()
    event.bot = MagicMock()
    event.bot.id = bot_id
    event.from_user = MagicMock()
    event.from_user.id = user_id
    return event


# --- BotIncludeFilter ---


@pytest.mark.asyncio
async def test_bot_include_filter_match():
    f = BotIncludeFilter(bot_id=100)
    event = _make_event(bot_id=100)
    assert await f(event) is True


@pytest.mark.asyncio
async def test_bot_include_filter_no_match():
    f = BotIncludeFilter(bot_id=100)
    event = _make_event(bot_id=200)
    assert await f(event) is False


# --- BotExcludeFilter ---


@pytest.mark.asyncio
async def test_bot_exclude_filter_allows_unlisted():
    blocked = {200, 300}
    f = BotExcludeFilter(blocked_bot_ids=blocked)
    event = _make_event(bot_id=100)
    assert await f(event) is True


@pytest.mark.asyncio
async def test_bot_exclude_filter_blocks_listed():
    blocked = {200, 300}
    f = BotExcludeFilter(blocked_bot_ids=blocked)
    event = _make_event(bot_id=200)
    assert await f(event) is False


@pytest.mark.asyncio
async def test_bot_exclude_filter_empty_set_allows_all():
    f = BotExcludeFilter()
    event = _make_event(bot_id=999)
    assert await f(event) is True


@pytest.mark.asyncio
async def test_bot_exclude_filter_mutability():
    """blocked_bot_ids — мутабельный set, изменения отражаются сразу."""
    blocked: set[int] = set()
    f = BotExcludeFilter(blocked_bot_ids=blocked)
    event = _make_event(bot_id=100)

    # Изначально пропускает
    assert await f(event) is True

    # Добавляем в blocked — теперь блокирует
    blocked.add(100)
    assert await f(event) is False

    # Убираем — снова пропускает
    blocked.discard(100)
    assert await f(event) is True


# --- ABGroupFilter ---


@pytest.mark.asyncio
async def test_ab_group_filter_match():
    resolver = AsyncMock(return_value="variant_a")
    f = ABGroupFilter(group_name="variant_a", resolver=resolver)
    event = _make_event(bot_id=100, user_id=42)
    assert await f(event) is True
    resolver.assert_awaited_once_with(100, 42)


@pytest.mark.asyncio
async def test_ab_group_filter_no_match():
    resolver = AsyncMock(return_value="variant_b")
    f = ABGroupFilter(group_name="variant_a", resolver=resolver)
    event = _make_event(bot_id=100, user_id=42)
    assert await f(event) is False


@pytest.mark.asyncio
async def test_ab_group_filter_no_user():
    resolver = AsyncMock(return_value="variant_a")
    f = ABGroupFilter(group_name="variant_a", resolver=resolver)
    event = _make_event(bot_id=100)
    event.from_user = None
    assert await f(event) is False
    resolver.assert_not_awaited()
