from pyrogram import filters
from pyrogram.enums import ChatMemberStatus as CMS
from pyrogram.errors import PeerIdInvalid, RPCError, UserNotParticipant
from pyrogram.types import CallbackQuery, Message
from Powers import LOGGER
from Powers.bot_class import Gojo
from Powers.database.approve_db import Approve
from Powers.utils.custom_filters import admin_filter, command, owner_filter
from Powers.utils.extract_user import extract_user
from Powers.utils.kbhelpers import ikb
from Powers.utils.parser import mention_html
@Gojo.on_message(command("approve") & admin_filter)
async def approve_user(c: Gojo, m: Message):
    db = Approve(m.chat.id)
    chat_title = m.chat.title
    try:
        user_id, user_first_name, _ = await extract_user(c, m)
    except Exception:
        return
    if not user_id:
        await m.reply_text(
            "I don't know who you're talking about, you're going to need to specify a user!",
        )
        return
    try:
        member = await m.chat.get_member(user_id)
    except UserNotParticipant:
        await m.reply_text("This user is not in this chat!")
        return
    except RPCError as ef:
        await m.reply_text(
            f"Error: {ef}\nReport it using /bug",
        )
        return
    if member.status in (CMS.ADMINISTRATOR, CMS.OWNER):
        await m.reply_text(
            "User is already admin - blacklists and locks already don't apply to them.",
        )
        return
    already_approved = db.check_approve(user_id)
    if already_approved:
        await m.reply_text(
            f"{(await mention_html(user_first_name, user_id))} is already approved in {chat_title}",
        )
        return
    db.add_approve(user_id, user_first_name)
    # Allow all permissions
    try:
        await m.chat.unban_member(user_id=user_id)
    except RPCError as g:
        await m.reply_text(f"Error: {g}")
        return
    await m.reply_text(
        (
            f"{(await mention_html(user_first_name, user_id))} has been approved in {chat_title}!\n"
            "They will now be ignored by blacklists, locks and antiflood!"
        ),
    )
    return
@Gojo.on_message(
    command(["disapprove", "unapprove"]) & admin_filter,
)
async def disapprove_user(c: Gojo, m: Message):
    db = Approve(m.chat.id)
    chat_title = m.chat.title
    try:
        user_id, user_first_name, _ = await extract_user(c, m)
    except Exception:
        return
    already_approved = db.check_approve(user_id)
    if not user_id:
        await m.reply_text(
            "I don't know who you're talking about, you're going to need to specify a user!",
        )
        return
    try:
        member = await m.chat.get_member(user_id)
    except UserNotParticipant:
        if already_approved:  # If user is approved and not in chat, unapprove them.
            db.remove_approve(user_id)
        await m.reply_text("This user is not in this chat, unapproved them.")
        return
    except RPCError as ef:
        await m.reply_text(
            f"Error: {ef}\nReport it using /bug",
        )
        return
    if member.status in (CMS.OWNER, CMS.ADMINISTRATOR):
        await m.reply_text("This user is an admin, they can't be disapproved.")
        return
    if not already_approved:
        await m.reply_text(
            f"{(await mention_html(user_first_name, user_id))} isn't approved yet!",
        )
        return
    db.remove_approve(user_id)
    # Set permission same as of current user by fetching them from chat!
    await m.chat.restrict_member(
        user_id=user_id,
        permissions=m.chat.permissions,
    )
    await m.reply_text(
        f"{(await mention_html(user_first_name, user_id))} is no longer approved in {chat_title}.",
    )
    return
@Gojo.on_message(command("approved") & admin_filter)
async def check_approved(_, m: Message):
    db = Approve(m.chat.id)
    chat = m.chat
    chat_title = chat.title
    msg = "The following users are approved:\n"
    approved_people = db.list_approved()
    if not approved_people:
        await m.reply_text(f"No users are approved in {chat_title}.")
        return
    for user_id, user_name in approved_people:
        try:
            await chat.get_member(user_id)  # Check if user is in chat or not
        except UserNotParticipant:
            db.remove_approve(user_id)
            continue
        except PeerIdInvalid:
            pass
        msg += f"- `{user_id}`: {user_name}\n"
    await m.reply_text(msg)
    return
@Gojo.on_message(command("approval") & filters.group)
async def check_approval(c: Gojo, m: Message):
    db = Approve(m.chat.id)
    try:
        user_id, user_first_name, _ = await extract_user(c, m)
    except Exception:
        return
    check_approve = db.check_approve(user_id)
    if not user_id:
        await m.reply_text(
            "I don't know who you're talking about, you're going to need to specify a user!",
        )
        return
    if check_approve:
        await m.reply_text(
            f"{(await mention_html(user_first_name, user_id))} is an approved user. Locks, antiflood, and blacklists won't apply to them.",
        )
    else:
        await m.reply_text(
            f"{(await mention_html(user_first_name, user_id))} is not an approved user. They are affected by normal commands.",
        )
    return
@Gojo.on_message(
    command("unapproveall") & filters.group & owner_filter,
)
async def unapproveall_users(_, m: Message):
    db = Approve(m.chat.id)
    all_approved = db.list_approved()
    if not all_approved:
        await m.reply_text("No one is approved in this chat.")
        return
    await m.reply_text(
        "Are you sure you want to remove everyone who is approved in this chat?",
        reply_markup=ikb(
            [[("⚠️ Confirm", "unapprove_all"), ("❌ Cancel", "close_admin")]],
        ),
    )
    return
@Gojo.on_callback_query(filters.regex("^unapprove_all$"))
async def unapproveall_callback(_, q: CallbackQuery):
    user_id = q.from_user.id
    db = Approve(q.message.chat.id)
    approved_people = db.list_approved()
    user_status = (await q.message.chat.get_member(user_id)).status
    if user_status not in {CMS.OWNER, CMS.ADMINISTRATOR}:
        await q.answer(
            "You're not even an admin, don't try this explosive shit!",
            show_alert=True,
        )
        return
    db.unapprove_all()
    for i in approved_people:
        await q.message.chat.restrict_member(
            user_id=i[0],
            permissions=q.message.chat.permissions,
        )
    await q.message.delete()
    await q.answer("Disapproved all users!", show_alert=True)
    return
__PLUGIN__ = "approve"
_DISABLE_CMDS_ = ["approval"]
__alt_name__ = ["approved"]
__HELP__ = """
**Apporve**
**Admin commands:**
• /approval: Check a user's approval status in this chat.
• /approve: Approve of a user. Locks, blacklists, and antiflood won't apply to them anymore.
• /unapprove: Unapprove of a user. They will now be subject to blocklists.
• /approved: List all approved users.
• /unapproveall: Unapprove *ALL* users in a chat. This cannot be undone!
**Example:**
`/approve @username`: this approves a user in the chat."""