"""Decorators for handler access control."""
from __future__ import annotations

import functools
import logging

from telegram import Update
from telegram.constants import ParseMode
from telegram.error import BadRequest, Forbidden
from telegram.ext import ContextTypes

from bot import db
from bot.config import OWNER_ID
from bot.helpers import is_chat_admin

logger = logging.getLogger(__name__)


def admin_only(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        user = update.effective_user
        chat = update.effective_chat
        if not user or not chat:
            return
        if user.id == OWNER_ID:
            return await func(update, context, *args, **kwargs)
        if chat.type == "private":
            return await func(update, context, *args, **kwargs)
        if await is_chat_admin(context.bot, chat.id, user.id):
            return await func(update, context, *args, **kwargs)
        msg = update.effective_message
        if msg:
            try:
                await msg.reply_text("فقط ادمین‌ها میتوانند از این دستور استفاده کنند.")
            except (BadRequest, Forbidden):
                pass
        return None
    return wrapper


def sudo_only(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        user = update.effective_user
        if not user:
            return
        if user.id == OWNER_ID:
            return await func(update, context, *args, **kwargs)
        if await db.is_sudo(user.id):
            return await func(update, context, *args, **kwargs)
        msg = update.effective_message
        if msg:
            try:
                await msg.reply_text("فقط مدیران ارشد میتوانند از این دستور استفاده کنند.")
            except (BadRequest, Forbidden):
                pass
        return None
    return wrapper


def owner_only(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        user = update.effective_user
        if not user:
            return
        if user.id == OWNER_ID:
            return await func(update, context, *args, **kwargs)
        msg = update.effective_message
        if msg:
            try:
                await msg.reply_text("فقط مالک ربات میتواند از این دستور استفاده کند.")
            except (BadRequest, Forbidden):
                pass
        return None
    return wrapper


def bot_can_delete(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        chat = update.effective_chat
        if not chat:
            return
        try:
            member = await context.bot.get_chat_member(chat.id, context.bot.id)
            if member.status not in ("administrator", "creator"):
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات باید ادمین باشد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
            if not member.can_delete_messages:
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات دسترسی حذف پیام ندارد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
        except (BadRequest, Forbidden) as e:
            logger.warning("bot_can_delete check failed: %s", e)
            return None
        return await func(update, context, *args, **kwargs)
    return wrapper


def bot_can_pin(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        chat = update.effective_chat
        if not chat:
            return
        try:
            member = await context.bot.get_chat_member(chat.id, context.bot.id)
            if member.status not in ("administrator", "creator"):
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات باید ادمین باشد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
            if not member.can_pin_messages:
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات دسترسی سنجاق پیام ندارد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
        except (BadRequest, Forbidden) as e:
            logger.warning("bot_can_pin check failed: %s", e)
            return None
        return await func(update, context, *args, **kwargs)
    return wrapper


def bot_can_restrict(func):
    @functools.wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
        chat = update.effective_chat
        if not chat:
            return
        try:
            member = await context.bot.get_chat_member(chat.id, context.bot.id)
            if member.status not in ("administrator", "creator"):
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات باید ادمین باشد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
            if not member.can_restrict_members:
                msg = update.effective_message
                if msg:
                    try:
                        await msg.reply_text("ربات دسترسی محدودیت کاربران را ندارد.")
                    except (BadRequest, Forbidden):
                        pass
                return None
        except (BadRequest, Forbidden) as e:
            logger.warning("bot_can_restrict check failed: %s", e)
            return None
        return await func(update, context, *args, **kwargs)
    return wrapper
