from typing import Any, Dict

from aiogram import BaseMiddleware

from db import get_user, is_admin
from states import AuthStates


class AuthMiddleware(BaseMiddleware):
    async def __call__(
        self,
        handler: Any,
        event: Any,
        data: Dict[str, Any],
    ) -> Any:
        # Обрабатываем только сообщения и callback-запросы
        from aiogram.types import (
            CallbackQuery as AiogramCallbackQuery,
            Message as AiogramMessage,
        )

        # Служебные апдейты (например, my_chat_member) пропускаем без проверок
        if not isinstance(event, (AiogramMessage, AiogramCallbackQuery)):
            return await handler(event, data)

        user = event.from_user
        if user is None:
            return await handler(event, data)

        user_id = user.id

        # Разрешаем /start, /allow_user, /block_user и ввод пароля
        text = ""
        if isinstance(event, AiogramMessage):
            text = event.text or ""
        elif isinstance(event, AiogramCallbackQuery):
            text = event.data or ""

        base_cmd = text.split()[0] if text else ""

        if isinstance(event, AiogramMessage) and base_cmd in (
            "/start",
            "/allow_user",
            "/block_user",
        ):
            return await handler(event, data)

        state = data.get("state")
        if state is not None:
            current_state = await state.get_state()
            if current_state == AuthStates.AwaitingPassword.state:
                return await handler(event, data)

        # Админам разрешаем всё
        if await is_admin(user_id):
            return await handler(event, data)

        db_user = await get_user(user_id)
        if not db_user or not db_user.get("allow"):
            # У пользователя нет доступа
            if isinstance(event, AiogramMessage):
                await event.answer(
                    "У вас нет доступа к этому боту. Введите /start для авторизации или обратитесь к администратору."
                )
            elif isinstance(event, AiogramCallbackQuery):
                await event.answer("У вас нет доступа к этому боту.", show_alert=True)
            return None

        return await handler(event, data)

