from typing import Any

from aiogram import Bot
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
from aiogram.filters import BaseFilter
from aiogram.types import Message, ResultChatMemberUnion, CallbackQuery

from configs import ImportantID

# Настройка экспорта в модули
__all__ = ("IsChatCreator", "IsAdmin", "IsModerator", "IsOwner",)


class IsOwner(BaseFilter):
    """
    Фильтр для проверки, является ли пользователь владельцем бота.

    Args:
        send_error_message (bool): Если True, при попытке не- владельца выполнить команду,
                                   бот отправит сообщение об ошибке.

    Returns:
        bool | dict[str, Any]:
            - False, если пользователь не владелец и send_error_message=False
            - True, если пользователь является владельцем
            - dict с информацией о пользователе, если send_error_message=True

    Example:
        @router.message(IsOwner())
        async def cmd_handler(message: Message):
            ...

        @router.message(IsOwner(send_error_message=True))
        async def admin_only(message: Message):
            ...
    """

    def __init__(self, send_error_message: bool = False) -> None:
        """
        Инициализация фильтра.

        Args:
            send_error_message: Нужно ли отправлять сообщение при запрещенном доступе
        """
        self.send_error_message: bool = send_error_message

    async def __call__(self, update: Message | CallbackQuery, bot: Bot) -> bool | dict[str, Any]:
        """
        Проверяет, является ли пользователь владельцем.

        Args:
            update: Объект Message или CallbackQuery
            bot: Экземпляр бота (не используется, но требуется сигнатурой)

        Returns:
            bool | dict[str, Any]: Результат фильтра. Если пользователь владелец,
                                    возвращается True или dict с info. Иначе False
        """
        if not update.from_user:
            # Без from_user невозможно определить владельца
            return False

        user_id: int = update.from_user.id
        is_owner: bool = user_id in ImportantID.OWNERS_ID

        if not is_owner and self.send_error_message:
            # Отправляем предупреждение о доступе
            if isinstance(update, Message):
                await update.answer(text="⛔ Эта команда доступна только владельцу бота!")
            elif isinstance(update, CallbackQuery):
                await update.answer(text="⛔ Доступно только владельцу бота!", show_alert=True)
            return False

        # Если пользователь владелец — возвращаем словарь с дополнительной информацией
        if is_owner:
            return {
                "is_owner": True,
                "user_id": user_id,
                "owner_ids": ImportantID.OWNERS_ID
            }

        # Если не владелец и send_error_message=False
        return False


class IsChatCreator(BaseFilter):
    """
    Пользователь является создателем чата.

    Example:
        @router.message(IsChatCreator())
        async def handler(msg: Message):
            await msg.answer("Ты создатель этого чата 👑")
    """

    async def __call__(self, message: Message, bot: Bot) -> bool:
        try:
            member: ResultChatMemberUnion = await bot.get_chat_member(message.chat.id, message.from_user.id)
            return member.status == "creator"
        except (TelegramBadRequest, TelegramForbiddenError):
            return False


class IsAdmin(BaseFilter):
    """
    Пользователь является администратором (или создателем).

    Example:
        @router.message(IsAdmin())
        async def handler(msg: Message):
            await msg.answer("Ты админ ✅")
    """

    async def __call__(self, message: Message, bot: Bot) -> bool:
        try:
            member: ResultChatMemberUnion = await bot.get_chat_member(message.chat.id, message.from_user.id)
            return member.status in {"administrator", "creator"}
        except (TelegramBadRequest, TelegramForbiddenError):
            return False


class IsModerator(BaseFilter):
    """
    Администратор с модераторскими правами:
    - удаление сообщений
    - ограничение пользователей
    - закрепление сообщений

    Example:
        @router.message(IsModerator())
        async def handler(msg: Message):
            await msg.answer("Ты модератор ✅")
    """

    async def __call__(self, message: Message, bot: Bot) -> bool:
        try:
            member: ResultChatMemberUnion = await bot.get_chat_member(message.chat.id, message.from_user.id)

            if member.status == "creator":
                return True
            if member.status != "administrator":
                return False

            required_rights: list[bool] = [
                getattr(member, "can_delete_messages", False),
                getattr(member, "can_restrict_members", False),
                getattr(member, "can_pin_messages", False),
            ]
            return all(required_rights)

        except (TelegramBadRequest, TelegramForbiddenError):
            return False
