from typing import Callable, Awaitable, Any, Dict, Optional

from aiogram import BaseMiddleware
from aiogram.filters.command import CommandObject
from aiogram.types import TelegramObject, Message

from middleware.loggers import logger


class ReferralMiddleware(BaseMiddleware):
    """
    Middleware для перехвата и обработки реферальных ссылок (?start=...).

    Основные задачи:
    - Отслеживание перехода по deep-link (например, /start ref123)
    - Централизованное логирование
    - Возможность передачи кода дальше в хендлеры
    - Подготовка к сохранению кода в базу данных
    """

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

        Args:
            handler: Следующий обработчик в цепочке middleware
            event: Входящее событие (Message, CallbackQuery и др.)
            data: Контекстные данные, доступные хендлеру

        Returns:
            Результат работы следующего обработчика
        """
        # Проверяем, что событие — это именно сообщение
        if isinstance(event, Message):
            # Извлекаем объект команды (если был установлен фильтр CommandStart)
            command: Optional[CommandObject] = data.get("command")

            # Проверяем, что это именно команда /start с аргументом
            if command and command.command.casefold() == "start" and command.args:
                ref_code: str = command.args
                user_id: int = event.from_user.id
                username: Optional[str] = event.from_user.username

                # 👉 Здесь можно сохранить код в БД
                logger.debug(
                    f"[Referral] user={user_id}, username={username}, ref={ref_code}"
                )

                # Пробрасываем реф-код в data, чтобы использовать в хендлере
                data["ref_code"] = ref_code

        # Передаём управление дальше
        return await handler(event, data)
