"""اتصال ربات به روبیکا با کتابخانه rubpy  (pip install rubpy).

⚠️ فقط همین فایل به کتابخانه وابسته است. اگر نسخه‌ی rubpy شما نام متدها را
متفاوت دارد، فقط کلاس RubikaPlatform را اصلاح کنید.
حساب ربات باید در گروه «ادمین» باشد (حذف پیام + بن کردن).
"""
import asyncio
import time

from rubpy import Client, filters
from rubpy.types import Update

import config
from core import Core


class RubikaPlatform:
    def __init__(self, client: Client):
        self.c = client
        self._names: dict[str, str] = {}
        self._joined_cache: dict[tuple, tuple[float, bool]] = {}

    async def send(self, chat, text, reply_to=None):
        try:
            await self.c.send_message(chat, text, reply_to_message_id=reply_to)
        except Exception as e:
            print("send error:", e)

    async def delete(self, chat, msg_id):
        try:
            await self.c.delete_messages(chat, [msg_id])
        except Exception as e:
            print("delete error:", e)

    async def ban(self, chat, uid):
        try:
            await self.c.ban_group_member(chat, uid)
        except Exception as e:
            print("ban error:", e)

    async def is_admin(self, chat, uid) -> bool:
        try:
            res = await self.c.get_group_admin_members(chat)
            return any(m.member_guid == uid for m in res.in_chat_members)
        except Exception as e:
            print("admin check error:", e)
            return False

    async def members(self, chat):
        out, start = [], None
        try:
            while True:
                res = await self.c.get_group_all_members(chat, start_id=start)
                for m in res.in_chat_members:
                    out.append((m.member_guid, getattr(m, "username", None), getattr(m, "first_name", "") or ""))
                if not getattr(res, "has_continue", False):
                    break
                start = res.next_start_id
        except Exception as e:
            print("members error:", e)
        return out

    async def is_joined(self, channel, uid) -> bool:
        """عضویت در کانال (با کش ۵ دقیقه‌ای). اگر بررسی ممکن نبود، کاربر را رد نمی‌کند."""
        k = (channel, uid)
        c = self._joined_cache.get(k)
        if c and time.time() - c[0] < 300:
            return c[1]
        ok, start = False, None
        try:
            while True:
                res = await self.c.get_channel_all_members(channel, start_id=start)
                if any(m.member_guid == uid for m in res.in_chat_members):
                    ok = True
                    break
                if not getattr(res, "has_continue", False):
                    break
                start = res.next_start_id
        except Exception as e:
            print("join check error:", e)
            return True
        self._joined_cache[k] = (time.time(), ok)
        return ok

    # ---- کمکی‌های مخصوص هندلر ----
    async def user_name(self, guid) -> str:
        if guid in self._names:
            return self._names[guid]
        name = guid[-6:]
        try:
            info = await self.c.get_user_info(guid)
            u = info.user
            name = (u.first_name or "") + (" " + u.last_name if getattr(u, "last_name", "") else "")
            name = name.strip() or u.username or name
        except Exception:
            pass
        self._names[guid] = name
        return name

    async def reply_author(self, chat, reply_id):
        try:
            res = await self.c.get_messages_by_id(chat, [reply_id])
            return res.messages[0].author_object_guid
        except Exception as e:
            print("reply author error:", e)
            return None


async def main():
    async with Client(name=config.SESSION_NAME) as client:
        plat = RubikaPlatform(client)
        core = Core(plat)

        @client.on_message_updates(filters.is_group)
        async def on_message(update: Update):
            text = update.raw_text
            if not text:
                return
            chat, uid = update.object_guid, update.author_guid
            name = await plat.user_name(uid)
            reply_uid = None
            if update.reply_message_id:
                reply_uid = await plat.reply_author(chat, update.reply_message_id)
                if reply_uid:
                    core.db.touch_user(reply_uid, await plat.user_name(reply_uid))
            await core.handle(chat, uid, name, text, update.message_id, reply_uid)

        async def ticker():
            while True:
                await asyncio.sleep(5)
                try:
                    await core.tick()
                except Exception as e:
                    print("tick error:", e)

        asyncio.create_task(ticker())
        print("ربات روشن شد ✅")
        await client.run_until_disconnected()


if __name__ == "__main__":
    asyncio.run(main())
