from collections.abc import Awaitable, Callable
from typing import Any, TypedDict

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

from logger import logger


class UserInfo(TypedDict):
    user_id: int | None
    username: str | None
    action: str | None


class LoggingMiddleware(BaseMiddleware):
    """Middleware для логирования действий пользователя."""

    async def __call__(
        self,
        handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]],
        event: TelegramObject,
        data: dict[str, Any],
    ) -> Any:
        user_info = self._extract_user_info(event)

        if user_info["user_id"]:
            logger.info(
                f"Активность пользователя │ "
                f"ID: {str(user_info['user_id']).ljust(10)} │ "
                f"Имя: {user_info['username'] or '—':<15} │ "
                f"Действие: {user_info['action'] or '—'}"
            )

        return await handler(event, data)

    def _extract_user_info(self, event: TelegramObject) -> UserInfo:
        """Извлекает информацию о пользователе из различных типов событий."""
        result: UserInfo = {"user_id": None, "username": None, "action": None}

        if hasattr(event, "from_user") and isinstance(event.from_user, User):
            result["user_id"] = event.from_user.id
            result["username"] = event.from_user.username

            if isinstance(event, Message):
                result["action"] = f"Сообщение: {event.text}"
            elif isinstance(event, CallbackQuery):
                result["action"] = f"Обратный вызов: {event.data}"
            elif isinstance(event, InlineQuery):
                result["action"] = f"Inline запрос: {event.query}"

        return result
