import re
import asyncio
import random

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.constants import ChatType
from telegram.ext import Application, CallbackQueryHandler, MessageHandler, ContextTypes, filters

active_bets = {}
active_rps = {}
active_dice_games = {}


def register_bet_handlers(application: Application, coins, save_data):

    # --------- ایجاد شرط‌بندی ----------
    async def create_bet(update: Update, context: ContextTypes.DEFAULT_TYPE):
        message = update.message
        if message is None or not message.text:
            return
        parts = message.text.split(" ")
        if len(parts) != 2:
            return

        try:
            amount = int(parts[1])
        except ValueError:
            return

        if amount <= 0:
            return

        user_id = str(message.from_user.id)
        username = message.from_user.username
        creator_name = f"@{username}" if username else message.from_user.first_name
        chat_id = message.chat.id

        if coins.get(user_id, 0) < amount:
            await message.reply_text("❌ موجودی کافی برای شرط‌بندی نداری")
            return

        placeholder = await message.reply_text(
            f"=== SELF Vidal ===\n"
            f"- شرطبندی\n"
            f"- سکه : {amount}\n"
            f"- سازنده : {creator_name}\n"
            f"=== SELF Vidal ==="
        )
        msg_id = placeholder.message_id

        btn_join = InlineKeyboardButton(
            "پیوستن", callback_data=f"join_{chat_id}_{msg_id}", style="success"
        )
        btn_cancel = InlineKeyboardButton(
            "لغو شرط", callback_data=f"cancel_{chat_id}_{msg_id}", style="danger"
        )
        markup = InlineKeyboardMarkup([[btn_join, btn_cancel]])

        await context.bot.edit_message_reply_markup(chat_id=chat_id, message_id=msg_id, reply_markup=markup)

        active_bets[f"{chat_id}-{msg_id}"] = {
            "creator": user_id,
            "creator_name": creator_name,
            "amount": amount,
            "msg_id": msg_id,
            "chat_id": chat_id,
        }

    # --------- پیوستن به شرط ----------
    async def join_bet(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        try:
            _, chat_id, msg_id = query.data.split("_")
            chat_id = int(chat_id)
            msg_id = int(msg_id)
            key = f"{chat_id}-{msg_id}"
        except Exception:
            await query.answer("خطای داخلی", show_alert=True)
            return

        bet = active_bets.get(key)
        if not bet:
            await query.answer("این شرط دیگر فعال نیست", show_alert=True)
            return

        user_id = str(query.from_user.id)
        username = f"@{query.from_user.username}" if query.from_user.username else query.from_user.first_name

        creator = bet["creator"]
        creator_name = bet["creator_name"]
        amount = bet["amount"]

        if user_id == creator:
            await query.answer("نمی‌تونی تو شرط خودت شرکت کنی", show_alert=True)
            return

        if coins.get(user_id, 0) < amount:
            await query.answer("❌ موجودی کافی نداری", show_alert=True)
            return

        if coins.get(creator, 0) < amount:
            await query.answer("❌ سازنده موجودی کافی نداره", show_alert=True)
            return

        coins[user_id] -= amount
        coins[creator] -= amount
        save_data()

        await query.answer()

        await context.bot.edit_message_text(
            chat_id=chat_id,
            message_id=msg_id,
            text="⧈شرطبندی در حال اجراست…",
        )

        await asyncio.sleep(1.5)

        await context.bot.edit_message_text(
            chat_id=chat_id,
            message_id=msg_id,
            text="✯نتیجه در حال اعلام شدنه…",
        )

        await asyncio.sleep(2)

        winner_id = random.choice([creator, user_id])
        total = amount * 2

        if amount == 1:
            prize = total
        else:
            prize = int(total * 0.9)
        tax = total - prize

        coins[winner_id] = coins.get(winner_id, 0) + prize
        save_data()

        winner_name = creator_name if winner_id == creator else username
        loser_name = username if winner_id == creator else creator_name

        result_markup = InlineKeyboardMarkup([
            [
                InlineKeyboardButton("برنده", callback_data="noop", style="success"),
                InlineKeyboardButton(winner_name, callback_data="noop", style="success"),
            ],
            [
                InlineKeyboardButton("بازنده", callback_data="noop", style="danger"),
                InlineKeyboardButton(loser_name, callback_data="noop", style="danger"),
            ],
            [
                InlineKeyboardButton("جایزه برنده", callback_data="noop", style="success"),
                InlineKeyboardButton(f"{prize} سکه", callback_data="noop", style="success"),
            ],
            [
                InlineKeyboardButton("کارمزد", callback_data="noop", style="danger"),
                InlineKeyboardButton(f"{tax} سکه", callback_data="noop", style="danger"),
            ],
        ])

        await context.bot.edit_message_text(
            chat_id=chat_id,
            message_id=msg_id,
            text="=== SELF Vidal ===\nنتیجه‌ی شرط‌بندی:",
            reply_markup=result_markup,
        )

        active_bets.pop(key, None)

    # --------- لغو شرط ----------
    async def cancel_bet(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        try:
            _, chat_id, msg_id = query.data.split("_")
            chat_id = int(chat_id)
            msg_id = int(msg_id)
            key = f"{chat_id}-{msg_id}"
        except Exception:
            await query.answer("خطای داخلی", show_alert=True)
            return

        bet = active_bets.get(key)
        if not bet:
            await query.answer("این شرط وجود ندارد", show_alert=True)
            return

        if str(query.from_user.id) != bet["creator"]:
            await query.answer("فقط سازنده می‌تواند لغو کند", show_alert=True)
            return

        active_bets.pop(key, None)

        await context.bot.edit_message_text(
            chat_id=chat_id,
            message_id=msg_id,
            text="❌ شرط لغو شد",
        )

        await query.answer("شرط لغو شد", show_alert=True)

    # --------- ثبت هندلرها ----------
    application.add_handler(MessageHandler(
        ~filters.ChatType.PRIVATE & filters.Regex(r"^شرطبندی\s+\S+$"),
        create_bet,
    ))
    application.add_handler(CallbackQueryHandler(join_bet, pattern=r"^join_"))
    application.add_handler(CallbackQueryHandler(cancel_bet, pattern=r"^cancel_"))


def register_rps_handlers(application: Application, coins, save_data):

    # --------- ایجاد بازی ----------
    async def create_rps(update: Update, context: ContextTypes.DEFAULT_TYPE):
        message = update.message
        if message is None or not message.text:
            return
        match = re.fullmatch(r"سنگ کاغذ قیچی (\d+)", message.text)
        if not match:
            return

        amount = int(match.group(1))
        if amount <= 0:
            return

        user_id = str(message.from_user.id)
        username = message.from_user.username or message.from_user.first_name
        chat_id = message.chat.id

        if coins.get(user_id, 0) < amount:
            await message.reply_text("❌ موجودی کافی برای شروع بازی نداری")
            return

        placeholder = await message.reply_text(
            f"=== SELF Vidal ===\n"
            f"- سنگ کاغذ قیچی\n"
            f"- سکه : {amount}\n"
            f"- سازنده : @{username}\n"
            f"=== SELF Vidal ==="
        )
        msg_id = placeholder.message_id

        btn_join = InlineKeyboardButton(
            "پیوستن", callback_data=f"rpsjoin_{chat_id}_{msg_id}_{amount}", style="success"
        )
        btn_cancel = InlineKeyboardButton(
            "لغو بازی", callback_data=f"rpscancel_{chat_id}_{msg_id}", style="danger"
        )
        markup = InlineKeyboardMarkup([[btn_join, btn_cancel]])

        await context.bot.edit_message_reply_markup(chat_id=chat_id, message_id=msg_id, reply_markup=markup)

        active_rps[f"{chat_id}-{msg_id}"] = {
            "player1": user_id,
            "player1_name": username,
            "amount": amount,
            "msg_id": msg_id,
            "chat_id": chat_id,
            "player2": None,
            "player2_name": None,
            "player1_choice": None,
            "player2_choice": None,
        }

    # --------- لغو ----------
    async def cancel_rps(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        try:
            _, chat_id, msg_id = query.data.split("_")
            key = f"{chat_id}-{msg_id}"
        except Exception:
            await query.answer("خطای داخلی", show_alert=True)
            return

        game = active_rps.get(key)
        if not game:
            await query.answer("این بازی دیگر فعال نیست", show_alert=True)
            return

        if str(query.from_user.id) != game["player1"]:
            await query.answer("فقط سازنده می‌تواند لغو کند", show_alert=True)
            return

        active_rps.pop(key, None)

        await context.bot.edit_message_text(
            chat_id=int(chat_id),
            message_id=int(msg_id),
            text="❌ بازی سنگ کاغذ قیچی لغو شد",
        )

        await query.answer("بازی لغو شد", show_alert=True)

    # --------- پیوستن ----------
    async def join_rps(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        print(f"[DEBUG] join_rps triggered, data={query.data!r}, active_rps keys={list(active_rps.keys())}")
        try:
            _, chat_id, msg_id, amount_str = query.data.split("_")
            amount = int(amount_str)
            key = f"{chat_id}-{msg_id}"
        except Exception as e:
            print(f"[DEBUG] join_rps parse error: {e}")
            await query.answer("خطای داخلی", show_alert=True)
            return

        game = active_rps.get(key)
        if not game:
            await query.answer("این بازی دیگر فعال نیست", show_alert=True)
            return

        user_id = str(query.from_user.id)
        username = query.from_user.username or query.from_user.first_name

        if user_id == game["player1"]:
            await query.answer("نمی‌توانید در بازی خودتان شرکت کنید", show_alert=True)
            return

        if game["player2"] is not None:
            await query.answer("بازی پر شده", show_alert=True)
            return

        if coins.get(user_id, 0) < amount:
            await query.answer("موجودی کافی ندارید", show_alert=True)
            return

        if coins.get(game["player1"], 0) < amount:
            await query.answer("سازنده موجودی کافی ندارد", show_alert=True)
            return

        coins[user_id] -= amount
        coins[game["player1"]] -= amount
        save_data()

        game["player2"] = user_id
        game["player2_name"] = username

        await query.answer()

        markup = InlineKeyboardMarkup([[
            InlineKeyboardButton("سنگ 🪨", callback_data=f"rpsplay_{key}_سنگ", style="danger"),
            InlineKeyboardButton("کاغذ 📄", callback_data=f"rpsplay_{key}_کاغذ", style="success"),
            InlineKeyboardButton("قیچی ✂️", callback_data=f"rpsplay_{key}_قیچی", style="primary"),
        ]])

        await context.bot.edit_message_text(
            chat_id=int(chat_id),
            message_id=game["msg_id"],
            text=(
                "=== SELF Vidal ===\n"
                f"- بازیکن 1 : @{game['player1_name']}\n"
                f"- بازیکن 2 : @{game['player2_name']}\n"
                "=== SELF Vidal ==="
            ),
            reply_markup=markup,
        )

    # --------- انتخاب ----------
    async def play_rps(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        try:
            _, key, choice = query.data.split("_")
        except Exception:
            await query.answer("خطای داخلی", show_alert=True)
            return

        game = active_rps.get(key)
        if not game:
            await query.answer("این بازی دیگر فعال نیست", show_alert=True)
            return

        user_id = str(query.from_user.id)

        if user_id == game["player1"]:
            if game["player1_choice"]:
                await query.answer("قبلاً انتخاب کرده‌اید", show_alert=True)
                return
            game["player1_choice"] = choice

        elif user_id == game["player2"]:
            if game["player2_choice"]:
                await query.answer("قبلاً انتخاب کرده‌اید", show_alert=True)
                return
            game["player2_choice"] = choice

        else:
            await query.answer("شما بازیکن نیستید", show_alert=True)
            return

        await query.answer(f"انتخاب شما ثبت شد: {choice}", show_alert=True)

        if not (game["player1_choice"] and game["player2_choice"]):
            return

        p1 = game["player1_choice"]
        p2 = game["player2_choice"]

        emoji = {"سنگ": "🪨", "کاغذ": "📄", "قیچی": "✂️"}

        # مساوی
        if p1 == p2:
            coins[game["player1"]] += game["amount"]
            coins[game["player2"]] += game["amount"]
            save_data()

            await context.bot.edit_message_text(
                chat_id=int(game["chat_id"]),
                message_id=game["msg_id"],
                text=(
                    "=== SELF Vidal ===\n"
                    "- سنگ کاغذ قیچی\n"
                    "- مساوی\n"
                    "- سکه به هر دو بازیکن برگشت\n"
                    f"- انتخاب هر دو بازیکن : ({p1} {emoji[p1]})\n"
                    "=== SELF Vidal ==="
                ),
            )

        else:
            win = (
                "player1" if
                (p1 == "سنگ" and p2 == "قیچی") or
                (p1 == "کاغذ" and p2 == "سنگ") or
                (p1 == "قیچی" and p2 == "کاغذ")
                else "player2"
            )

            winner_id = game["player1"] if win == "player1" else game["player2"]
            winner_name = game["player1_name"] if win == "player1" else game["player2_name"]
            loser_name = game["player2_name"] if win == "player1" else game["player1_name"]

            winner_choice = p1 if win == "player1" else p2
            loser_choice = p2 if win == "player1" else p1

            total = game["amount"] * 2
            prize = int(total * 0.9)
            tax = total - prize

            coins[winner_id] += prize
            save_data()

            result_markup = InlineKeyboardMarkup([
                [
                    InlineKeyboardButton("برنده", callback_data="noop", style="success"),
                    InlineKeyboardButton(f"@{winner_name}", callback_data="noop", style="success"),
                ],
                [
                    InlineKeyboardButton("بازنده", callback_data="noop", style="danger"),
                    InlineKeyboardButton(f"@{loser_name}", callback_data="noop", style="danger"),
                ],
                [
                    InlineKeyboardButton("انتخاب برنده", callback_data="noop", style="success"),
                    InlineKeyboardButton(f"{winner_choice} {emoji[winner_choice]}", callback_data="noop", style="success"),
                ],
                [
                    InlineKeyboardButton("انتخاب بازنده", callback_data="noop", style="danger"),
                    InlineKeyboardButton(f"{loser_choice} {emoji[loser_choice]}", callback_data="noop", style="danger"),
                ],
                [
                    InlineKeyboardButton("جایزه برنده", callback_data="noop", style="success"),
                    InlineKeyboardButton(f"{prize} سکه", callback_data="noop", style="success"),
                ],
                [
                    InlineKeyboardButton("کارمزد", callback_data="noop", style="danger"),
                    InlineKeyboardButton(f"{tax} سکه", callback_data="noop", style="danger"),
                ],
            ])

            await context.bot.edit_message_text(
                chat_id=int(game["chat_id"]),
                message_id=game["msg_id"],
                text="=== SELF Vidal ===\nنتیجه‌ی سنگ کاغذ قیچی:",
                reply_markup=result_markup,
            )

        active_rps.pop(key, None)

    # --------- ثبت هندلرها ----------
    application.add_handler(MessageHandler(
        ~filters.ChatType.PRIVATE & filters.Regex(r"^سنگ کاغذ قیچی \d+$"),
        create_rps,
    ))
    application.add_handler(CallbackQueryHandler(cancel_rps, pattern=r"^rpscancel_"))
    application.add_handler(CallbackQueryHandler(join_rps, pattern=r"^rpsjoin_"))
    application.add_handler(CallbackQueryHandler(play_rps, pattern=r"^rpsplay_"))


###############################################
#         بازی تاس گروهی (۴ نفره)             #
###############################################
DICE_FILL_TIMEOUT = 300   # ۵ دقیقه فرصت پر شدن بازی
DICE_ROUND_TIME = 30      # ۳۰ ثانیه فرصت هر دور


def register_dice_handlers(application: Application, coins, save_data):

    async def safe_edit(context, chat_id, message_id, text, reply_markup=None):
        """ادیت امن پیام؛ اگه به فلود کنترل تلگرام خورد یا هر خطای دیگه‌ای پیش اومد، کرش نمی‌کنه."""
        try:
            await context.bot.edit_message_text(
                chat_id=chat_id, message_id=message_id, text=text, reply_markup=reply_markup
            )
        except Exception:
            pass

    def render_names(game, round_players):
        """متن لیست بازیکن‌ها رو می‌سازه؛ اگه کسی تاس انداخته باشه، عددش رو هم نشون میده."""
        lines = []
        rolls = game.get("rolls", {})
        for uid in game["players"]:
            name = game["names"][uid]
            if round_players is not None and uid not in round_players:
                lines.append(f"{name}: ❌ حذف شد")
            elif uid in rolls:
                lines.append(f"{name}: {rolls[uid]}")
            else:
                lines.append(f"{name}:")
        return "\n".join(lines)

    # ---------- ساخت بازی ----------
    async def create_dice_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
        message = update.message
        match = re.fullmatch(r"بازی\s+(\d+)", message.text.strip())
        if not match:
            return

        amount = int(match.group(1))
        if amount <= 0:
            return

        user_id = str(message.from_user.id)
        username = message.from_user.username or message.from_user.first_name
        chat_id = message.chat.id

        if coins.get(user_id, 0) < amount:
            await message.reply_text("❌ موجودی کافی برای ساخت بازی نداری")
            return

        # کسر سکه سازنده به‌عنوان بازیکن اول (امانی)
        coins[user_id] -= amount
        save_data()

        game = {
            "chat_id": chat_id,
            "amount": amount,
            "players": [user_id],
            "names": {user_id: f"@{username}" if message.from_user.username else username},
            "state": "waiting",
        }

        text = (
            "=== SELF Vidal ===\n"
            f"بازی تاس ({amount} سکه هرنفر)\n"
            f"{render_names(game, None)}\n\n"
            "منتظر تکمیل ظرفیت (۴ نفر)…"
        )
        markup = InlineKeyboardMarkup([[
            InlineKeyboardButton("🎲 پیوستن", callback_data="dicejoin_pending", style="success"),
            InlineKeyboardButton("لغو بازی", callback_data="dicecancel_pending", style="danger"),
        ]])

        placeholder = await message.reply_text(text, reply_markup=markup)
        msg_id = placeholder.message_id
        game["msg_id"] = msg_id
        key = f"{chat_id}-{msg_id}"
        active_dice_games[key] = game

        real_markup = InlineKeyboardMarkup([[
            InlineKeyboardButton("🎲 پیوستن", callback_data=f"dicejoin_{key}", style="success"),
            InlineKeyboardButton("لغو بازی", callback_data=f"dicecancel_{key}", style="danger"),
        ]])
        await context.bot.edit_message_reply_markup(chat_id=chat_id, message_id=msg_id, reply_markup=real_markup)

        asyncio.create_task(fill_timeout_task(key, context))

    # ---------- تایمر ۵ دقیقه‌ای پر شدن ----------
    async def fill_timeout_task(key, context):
        await asyncio.sleep(DICE_FILL_TIMEOUT)
        game = active_dice_games.get(key)
        if not game or game["state"] != "waiting":
            return

        # هنوز پر نشده -> بازگرداندن سکه‌ها
        for uid in game["players"]:
            coins[uid] = coins.get(uid, 0) + game["amount"]
        save_data()

        chat_id, msg_id = key.split("-")
        try:
            await context.bot.edit_message_text(
                chat_id=int(chat_id),
                message_id=int(msg_id),
                text="=== SELF Vidal ===\n❌ بازی تاس بسته شد (ظرفیت پر نشد و سکه‌ها بازگشت)",
            )
        except Exception:
            pass

        active_dice_games.pop(key, None)

    # ---------- لغو بازی (فقط قبل از پر شدن) ----------
    async def cancel_dice_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        key = query.data.split("_", 1)[1]
        game = active_dice_games.get(key)
        if not game:
            await query.answer("این بازی دیگر فعال نیست", show_alert=True)
            return

        if str(query.from_user.id) != game["players"][0]:
            await query.answer("فقط سازنده می‌تواند لغو کند", show_alert=True)
            return

        if game["state"] != "waiting":
            await query.answer("بازی از حالت انتظار خارج شده و قابل لغو نیست", show_alert=True)
            return

        for uid in game["players"]:
            coins[uid] = coins.get(uid, 0) + game["amount"]
        save_data()

        active_dice_games.pop(key, None)

        await query.edit_message_text("=== SELF Vidal ===\n❌ بازی تاس لغو شد (سکه‌ها بازگشت)")
        await query.answer("بازی لغو شد")

    # ---------- پیوستن به بازی ----------
    async def join_dice_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        key = query.data.split("_", 1)[1]
        game = active_dice_games.get(key)
        if not game:
            await query.answer("این بازی دیگر فعال نیست", show_alert=True)
            return

        if game["state"] != "waiting":
            await query.answer("این بازی دیگر پیوستن قبول نمی‌کند", show_alert=True)
            return

        user_id = str(query.from_user.id)
        if user_id in game["players"]:
            await query.answer("قبلاً به این بازی پیوسته‌ای", show_alert=True)
            return

        if coins.get(user_id, 0) < game["amount"]:
            await query.answer("❌ موجودی کافی نداری", show_alert=True)
            return

        username = query.from_user.username or query.from_user.first_name
        coins[user_id] -= game["amount"]
        game["players"].append(user_id)
        game["names"][user_id] = f"@{username}" if query.from_user.username else username
        save_data()

        await query.answer("پیوستی!")

        chat_id = game["chat_id"]
        msg_id = game["msg_id"]

        if len(game["players"]) < 4:
            text = (
                "=== SELF Vidal ===\n"
                f"بازی تاس ({game['amount']} سکه هرنفر)\n"
                f"{render_names(game, None)}\n\n"
                f"منتظر تکمیل ظرفیت ({len(game['players'])}/4)…"
            )
            markup = InlineKeyboardMarkup([[
                InlineKeyboardButton("🎲 پیوستن", callback_data=f"dicejoin_{key}", style="success"),
                InlineKeyboardButton("لغو بازی", callback_data=f"dicecancel_{key}", style="danger"),
            ]])
            await context.bot.edit_message_text(chat_id=chat_id, message_id=msg_id, text=text, reply_markup=markup)
            return

        # ظرفیت تکمیل شد -> شروع دور اول
        game["state"] = "rolling"
        await start_round(key, context, list(game["players"]))

    # ---------- شروع یک دور ----------
    async def start_round(key, context, round_players):
        game = active_dice_games[key]
        game["round_players"] = round_players
        game["rolls"] = {}

        markup = InlineKeyboardMarkup([[
            InlineKeyboardButton("🎲 انداختن تاس", callback_data=f"diceroll_{key}", style="primary"),
        ]])

        text = (
            "=== SELF Vidal ===\n"
            f"بازی تاس ({game['amount']} سکه هرنفر)\n"
            f"{render_names(game, round_players)}\n\n"
            f"⏳ {DICE_ROUND_TIME} ثانیه فرصت برای انداختن تاس"
        )
        await safe_edit(context, game["chat_id"], game["msg_id"], text, markup)

        asyncio.create_task(round_timer_task(key, context))

    # ---------- تایمر ۳۰ ثانیه‌ای هر دور ----------
    async def round_timer_task(key, context):
        for remaining in range(DICE_ROUND_TIME - 1, -1, -1):
            await asyncio.sleep(1)

            game = active_dice_games.get(key)
            if not game or game["state"] != "rolling":
                return

            round_players = game["round_players"]
            if len(game["rolls"]) >= len(round_players):
                break  # همه زودتر انداختن، نیازی به ادامه‌ی شمارش نیست

            # برای جلوگیری از فلود کنترل تلگرام، فقط هر ۳ ثانیه یک‌بار ادیت میشه
            if remaining % 3 != 0:
                continue

            markup = InlineKeyboardMarkup([[
                InlineKeyboardButton("🎲 انداختن تاس", callback_data=f"diceroll_{key}", style="primary"),
            ]])
            text = (
                "=== SELF Vidal ===\n"
                f"بازی تاس ({game['amount']} سکه هرنفر)\n"
                f"{render_names(game, round_players)}\n\n"
                f"⏳ {remaining} ثانیه فرصت برای انداختن تاس "
                f"({len(game['rolls'])}/{len(round_players)} انداختن)"
            )
            await safe_edit(context, game["chat_id"], game["msg_id"], text, markup)

        await resolve_round(key, context)

    # ---------- انداختن تاس ----------
    async def roll_dice(update: Update, context: ContextTypes.DEFAULT_TYPE):
        query = update.callback_query
        key = query.data.split("_", 1)[1]
        game = active_dice_games.get(key)
        if not game or game["state"] != "rolling":
            await query.answer("این دور دیگر فعال نیست", show_alert=True)
            return

        user_id = str(query.from_user.id)
        if user_id not in game["round_players"]:
            await query.answer("شما در این دور بازی نیستید", show_alert=True)
            return

        if user_id in game["rolls"]:
            await query.answer("قبلاً تاس انداخته‌ای", show_alert=True)
            return

        value = random.randint(1, 6) + random.randint(1, 6)
        game["rolls"][user_id] = value

        await query.answer(f"عدد تو: {value}", show_alert=True)

        # نمایش فوری عدد جلوی آیدی همون لحظه (بدون منتظر موندن برای تیک بعدی تایمر)
        round_players = game["round_players"]
        markup = InlineKeyboardMarkup([[
            InlineKeyboardButton("🎲 انداختن تاس", callback_data=f"diceroll_{key}", style="primary"),
        ]])
        text = (
            "=== SELF Vidal ===\n"
            f"بازی تاس ({game['amount']} سکه هرنفر)\n"
            f"{render_names(game, round_players)}\n\n"
            f"({len(game['rolls'])}/{len(round_players)} انداختن)"
        )
        await safe_edit(context, game["chat_id"], game["msg_id"], text, markup)

        if len(game["rolls"]) >= len(round_players):
            await resolve_round(key, context)

    # ---------- پایان دور و تعیین نتیجه ----------
    async def resolve_round(key, context):
        game = active_dice_games.get(key)
        if not game or game["state"] != "rolling":
            return

        round_players = game["round_players"]

        # هرکسی که نینداخته، ربات خودکار براش می‌ندازه
        for uid in round_players:
            if uid not in game["rolls"]:
                game["rolls"][uid] = random.randint(1, 6) + random.randint(1, 6)

        max_value = max(game["rolls"].values())
        winners = [uid for uid in round_players if game["rolls"][uid] == max_value]

        result_text = render_names(game, round_players)

        if len(winners) == 1:
            winner_id = winners[0]
            total_pot = game["amount"] * len(game["players"])
            tax = int(total_pot * 0.1)
            prize = total_pot - tax

            coins[winner_id] = coins.get(winner_id, 0) + prize
            save_data()

            winner_name = game["names"][winner_id]
            winner_roll = game["rolls"][winner_id]

            result_markup = InlineKeyboardMarkup([
                [
                    InlineKeyboardButton("برنده", callback_data="noop", style="success"),
                    InlineKeyboardButton(winner_name, callback_data="noop", style="success"),
                ],
                [
                    InlineKeyboardButton("سکه", callback_data="noop", style="success"),
                    InlineKeyboardButton(f"{prize} سکه", callback_data="noop", style="success"),
                ],
                [
                    InlineKeyboardButton("تاس", callback_data="noop", style="primary"),
                    InlineKeyboardButton(f"{winner_roll}", callback_data="noop", style="primary"),
                ],
                [
                    InlineKeyboardButton("کارمزد", callback_data="noop", style="danger"),
                    InlineKeyboardButton(f"{tax} سکه", callback_data="noop", style="danger"),
                ],
            ])

            text = (
                "=== SELF Vidal ===\n"
                f"نتیجه‌ی بازی تاس:\n{result_text}\n"
            )
            await safe_edit(context, game["chat_id"], game["msg_id"], text, result_markup)

            active_dice_games.pop(key, None)
            return

        # مساوی -> دور بعدی فقط بین برنده‌های مساوی
        text = (
            "=== SELF Vidal ===\n"
            f"نتیجه‌ی این دور:\n{result_text}\n\n"
            "⚖️ مساوی! دور بعدی فقط بین نفرات مساوی…"
        )
        await safe_edit(context, game["chat_id"], game["msg_id"], text)

        await asyncio.sleep(2)
        await start_round(key, context, winners)

    # ---------- ثبت هندلرها ----------
    application.add_handler(MessageHandler(
        ~filters.ChatType.PRIVATE & filters.Regex(r"^بازی\s+\d+$"),
        create_dice_game,
    ))
    application.add_handler(CallbackQueryHandler(join_dice_game, pattern=r"^dicejoin_"))
    application.add_handler(CallbackQueryHandler(cancel_dice_game, pattern=r"^dicecancel_"))
    application.add_handler(CallbackQueryHandler(roll_dice, pattern=r"^diceroll_"))