"""Global ban — blacklist a user across all groups Bobi admins.

Inspired by common gban systems (Marie/Antidote/etc.).

Owner/sudo can add/remove gbans. When a globally-banned user joins or sends a
message, the bot will auto-ban them from the chat.
"""
from __future__ import annotations

import logging
from typing import Optional, Tuple

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.decorators import owner_only, sudo_only
from bot.helpers import resolve_target, user_link_raw
from bot.persian_router import register_mixed

logger = logging.getLogger(__name__)


# ───────── Helpers ─────────


async def _extract_target_and_reason(bot, message) -> Tuple[Optional[int], str]:
    """Get (user_id, reason) from reply or args. Reason is the rest of the args joined."""
    if message.reply_to_message and message.reply_to_message.from_user:
        target = message.reply_to_message.from_user.id
        parts = (message.text or "").split(maxsplit=1)
        reason = parts[1] if len(parts) > 1 else ""
        return target, reason.strip()

    args = (message.text or "").split()
    if len(args) < 2:
        return None, ""
    arg = args[1].strip()
    if arg.startswith("@"):
        try:
            chat = await bot.get_chat(arg)
            target = chat.id
        except BadRequest:
            return None, ""
    elif arg.lstrip("-").isdigit():
        target = int(arg)
    else:
        return None, ""
    rest = args[2:]
    reason = " ".join(rest).strip()
    return target, reason


def _user_name(uid: int) -> str:
    return f'<code>{uid}</code>'


# ───────── Commands ─────────
@sudo_only
async def gban_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Globally ban a user. Reply to a message or pass user_id [reason]."""
    chat = update.effective_chat
    user_id, reason = await _extract_target_and_reason(context.bot, update.message)
    if not user_id:
        await update.message.reply_text(
            "❌ استفاده: روی پیام کاربر ریپلای کنید یا <code>gban user_id [دلیل]</code>",
            parse_mode=ParseMode.HTML,
        )
        return

    if user_id == context.bot.id:
        await update.message.reply_text("🤖 به خودم دست نزن :)")
        return

    banner = update.effective_user.id
    await db.add_global_ban(user_id, reason or None, banner)
    await update.message.reply_text(
        f"🚫 کاربر {_user_name(user_id)} به صورت سراسری بن شد."
        + (f"\n📝 دلیل: {reason}" if reason else ""),
        parse_mode=ParseMode.HTML,
    )

    # Try to ban from the current chat too
    try:
        await context.bot.ban_chat_member(chat.id, user_id)
    except (BadRequest, Forbidden):
        pass


@sudo_only
async def ungban_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Remove a user from the global ban list."""
    user_id = await resolve_target(context.bot, update.message)
    if not user_id:
        await update.message.reply_text(
            "❌ استفاده: روی پیام کاربر ریپلای کنید یا <code>ungban user_id</code>",
            parse_mode=ParseMode.HTML,
        )
        return
    await db.remove_global_ban(user_id)
    await update.message.reply_text(
        f"✅ کاربر {_user_name(user_id)} از لیست بن سراسری خارج شد.",
        parse_mode=ParseMode.HTML,
    )


@sudo_only
async def gbancount_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Show the total number of globally banned users."""
    try:
        row = await db._fetchone("SELECT COUNT(*) AS n FROM global_bans")
        n = row["n"] if row else 0
    except Exception as e:
        await update.message.reply_text(f"⚠️ خطا: {e}")
        return
    await update.message.reply_text(
        f"📊 تعداد کاربران بن سراسری: <b>{n}</b>",
        parse_mode=ParseMode.HTML,
    )


@sudo_only
async def gbaninfo_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Show info about a globally banned user."""
    user_id = await resolve_target(context.bot, update.message)
    if not user_id:
        await update.message.reply_text(
            "❌ استفاده: روی پیام ریپلای کنید یا <code>gbaninfo user_id</code>",
            parse_mode=ParseMode.HTML,
        )
        return
    try:
        row = await db._fetchone(
            "SELECT user_id, reason, banned_by, created_at FROM global_bans WHERE user_id=?",
            (user_id,),
        )
    except Exception as e:
        await update.message.reply_text(f"⚠️ خطا: {e}")
        return

    if not row:
        await update.message.reply_text("ℹ️ این کاربر بن سراسری نیست.")
        return
    await update.message.reply_text(
        f"🚫 <b>{_user_name(user_id)}</b>\n\n"
        f"• شناسه: <code>{row['user_id']}</code>\n"
        f"• دلیل: {row['reason'] or '—'}\n"
        f"• توسط: <code>{row['banned_by'] or '—'}</code>",
        parse_mode=ParseMode.HTML,
    )


@owner_only
async def gbanlist_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """List all globally banned users (owner only)."""
    try:
        rows = await db._fetchall(
            "SELECT user_id, reason, created_at FROM global_bans ORDER BY created_at DESC LIMIT 100"
        )
    except Exception as e:
        await update.message.reply_text(f"⚠️ خطا: {e}")
        return
    if not rows:
        await update.message.reply_text("ℹ️ لیست بن سراسری خالی است.")
        return
    lines = [
        f"• <code>{r['user_id']}</code>" + (f" — {r['reason']}" if r['reason'] else "")
        for r in rows
    ]
    text = "🚫 <b>لیست بن سراسری</b> (۱۰۰ مورد آخر):\n\n" + "\n".join(lines[:50])
    if len(lines) > 50:
        text += f"\n\n… و {len(lines) - 50} مورد دیگر"
    await update.message.reply_text(text, parse_mode=ParseMode.HTML)


# ───────── Listener hooks ─────────
async def check_and_ban(context: ContextTypes.DEFAULT_TYPE, user_id: int, chat_id: int) -> bool:
    """If user is globally banned, ban them from chat. Returns True if banned."""
    if not await db.is_globally_banned(user_id):
        return False
    try:
        await context.bot.ban_chat_member(chat_id, user_id)
        return True
    except (BadRequest, Forbidden):
        return False


# ───────── Registration ─────────
def register(app) -> None:
    register_mixed(
        app,
        {
            "gban": gban_cmd,
            "ungban": ungban_cmd,
            "gbancount": gbancount_cmd,
            "gbaninfo": gbaninfo_cmd,
            "gbanlist": gbanlist_cmd,
        },
        {
            "بن سراسری": gban_cmd,
            "بن گلوبال": gban_cmd,
            "حذف بن سراسری": ungban_cmd,
            "رفع بن سراسری": ungban_cmd,
            "تعداد بن سراسری": gbancount_cmd,
            "آمار بن سراسری": gbancount_cmd,
            "اطلاعات بن سراسری": gbaninfo_cmd,
            "وضعیت بن سراسری": gbaninfo_cmd,
            "لیست بن سراسری": gbanlist_cmd,
            "بن شده های سراسری": gbanlist_cmd,
        },
    )
