from typing import Callable, Awaitable, Any, Dict

from aiogram import BaseMiddleware
from aiogram.types import Message, CallbackQuery, TelegramObject

from database import db

__all__ = ("BanCheckMiddleware",)

class BanCheckMiddleware(BaseMiddleware):
    """
    Middleware для проверки забанен ли пользователь.
    Если пользователь забанен в боте - блокирует все его действия.
    """

    async def __call__(
            self,
            handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
            event: TelegramObject,
            data: Dict[str, Any]
    ) -> Any:
        """
        Проверяет каждый входящий запрос на наличие пользователя в черном списке.

        Args:
            handler: Следующий обработчик
            event: Событие (сообщение, callback и т.д.)
            data: Данные контекста

        Returns:
            Результат обработчика или None если пользователь забанен
        """
        # Извлекаем информацию о пользователе из события
        user = await self._extract_user(event)

        if user is None:
            # Не смогли определить пользователя - пропускаем
            return await handler(event, data)

        # Проверяем в базе данных статус пользователя
        user_db = await db.get_user(user.id)

        if user_db and user_db.status == "banned":
            # Пользователь забанен - блокируем запрос
            await self._send_ban_message(event, data)
            return None

        # Пользователь не забанен - пропускаем запрос дальше
        return await handler(event, data)

    @staticmethod
    async def _extract_user(event: TelegramObject) -> Any:
        """
        Извлекает пользователя из разных типов событий.

        Args:
            event: Событие Telegram

        Returns:
            Объект пользователя или None
        """
        if isinstance(event, Message):
            return event.from_user
        elif isinstance(event, CallbackQuery):
            return event.from_user
        # Можно добавить другие типы событий при необходимости
        return None

    @staticmethod
    async def _send_ban_message(event: TelegramObject, data: Dict[str, Any]) -> None:
        """
        Отправляет сообщение о бане пользователю.

        Args:
            event: Событие которое triggered проверку
            data: Данные контекста с ботом
        """
        bot = data.get('bot')

        if not bot:
            return

        chat_id = None
        message_id = None

        # Определяем куда отправлять сообщение в зависимости от типа события
        if isinstance(event, Message):
            chat_id = event.chat.id
            message_id = event.message_id
        elif isinstance(event, CallbackQuery) and event.message:
            chat_id = event.message.chat.id
            message_id = event.message.message_id

        if chat_id:
            try:
                if isinstance(event, CallbackQuery):
                    # Для callback запросов отвечаем уведомлением
                    await event.answer("🚫 Вы заблокированы в боте!", show_alert=True)
                else:
                    # Для сообщений отправляем новое сообщение
                    await bot.send_message(
                        chat_id=chat_id,
                        text="🚫 Вы заблокированы в боте!",
                        reply_to_message_id=message_id
                    )
            except Exception:
                # Игнорируем ошибки отправки (пользователь мог заблокировать бота)
                pass
