import asyncio
import re
from datetime import datetime
import pymysql
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes,CallbackQueryHandler
import random
import string

TOKEN = '8110161043:AAHUpHA9x2KXCvGhJfDESZncFB2_8EAZR_A'
BOT_USERNAME = 'lobster123_bot'
CONTROLLER = "Teolllong"

current_game_id = None  # 当前游戏ID

minBanker = 1000
bankerDetectTime = 10
betDetectTime = 10
max_attempts = 3
bet_min_ratio = 0.01
bet_max_ratio = 0.1

# 全局状态
listening = False
betting = False
awaiting_result = False
final_result = None
highest_bid = 0
highest_user = ""
attempt = 0
force_stop = False
bet_min = 0
bet_max = 0
bets = {}  # username -> list of {'type': str, 'amount': int}

group_chat_id = None

waiting_for_continue = None  # None or 庄家username
wait_continue_task = None

valid_types = ['单数', '双数', '大', '小']

def get_user_credit(username):
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute("SELECT credit FROM users WHERE username = %s AND status = 1", (username,))
                row = cursor.fetchone()
                if row:
                    return float(row['credit'])
    except Exception as e:
        print(f"[获取用户余额异常]: {e}")
    return 0

def generate_referred_code(length=5):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choices(chars, k=length))

def is_user_registered(telegram_id):
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute(
                    "SELECT status FROM users WHERE telegram_id = %s", 
                    (str(telegram_id),)
                )
                row = cursor.fetchone()
                if row:
                    if row['status'] == 1:
                        return True
                    elif row['status'] == 2:
                        return "rejected"  # 被拒绝
                return False
    except Exception as e:
        print(f"[检查注册异常]: {e}")
        return False

def register_user(telegram_id, username):
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute(
                    "INSERT IGNORE INTO users (telegram_id, username, status, create_time) VALUES (%s, %s, %s, NOW())",
                    (str(telegram_id), username, 0)
                )
                conn.commit()
                return True
    except Exception as e:
        print(f"[注册异常]: {e}")
        return False

async def handle_register_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    username = query.from_user.username
    telegram_id = str(query.from_user.id)
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    referred_code = generate_referred_code()

    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with connection:
            with connection.cursor() as cursor:
                # 先检查是否已注册
                cursor.execute("SELECT status FROM users WHERE telegram_id = %s", (telegram_id,))
                row = cursor.fetchone()

                if row:
                    if row['status'] == 1:
                        await query.edit_message_text("✅ 你已经是注册用户！")
                    elif row['status'] == 0:
                        await query.edit_message_text("⏳ 你已经提交过注册，请等待审核或联系客服。")
                    elif row['status'] == 2:
                        await query.edit_message_text("❌ 你的注册被拒绝，请联系客服。")
                else:
                    # 不存在，插入新用户
                    cursor.execute(
                        "INSERT INTO users (username, telegram_id, status, create_time, referred_code) VALUES (%s, %s, %s, %s, %s)",
                        (username, telegram_id, 0, now, referred_code)
                    )
                    connection.commit()
                    await query.edit_message_text("✅ 注册成功！等待管理员审核通过后即可使用。")

    except Exception as e:
        print(f"[注册异常]: {e}")
        await query.edit_message_text("❌ 注册时发生错误，请稍后再试。")



# 📌 从数据库加载配置
def update_config_from_db():
    global TOKEN, BOT_USERNAME, CONTROLLER
    global minBanker, bankerDetectTime, betDetectTime, max_attempts, bet_min_ratio, bet_max_ratio

    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',  # <<< 请改成真实密码
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with connection:
            with connection.cursor() as cursor:
                cursor.execute("SELECT key_name, value FROM bot_config")
                rows = cursor.fetchall()
                config = {row['key_name']: row['value'] for row in rows}

                TOKEN = config.get('TOKEN', TOKEN)
                BOT_USERNAME = config.get('BOT_USERNAME', BOT_USERNAME)
                CONTROLLER = config.get('CONTROLLER', CONTROLLER)

                minBanker = int(config.get('minBanker', minBanker))
                bankerDetectTime = int(config.get('bankerDetectTime', bankerDetectTime))
                betDetectTime = int(config.get('betDetectTime', betDetectTime))
                max_attempts = int(config.get('max_attempts', max_attempts))
                bet_min_ratio = float(config.get('bet_min_ratio', bet_min_ratio))
                bet_max_ratio = float(config.get('bet_max_ratio', bet_max_ratio))

                print("[配置已更新]")
    except Exception as e:
        print(f"[配置更新异常]: {e}")

async def handle_check_balance_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    telegram_id = str(query.from_user.id)

    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with connection:
            with connection.cursor() as cursor:
                cursor.execute("SELECT credit FROM users WHERE telegram_id = %s AND status = 1 LIMIT 1", (telegram_id,))
                row = cursor.fetchone()

                if row:
                    credit = row['credit']
                    await query.edit_message_text(f"💰 你的余额是：{credit:.2f}")
                else:
                    await query.edit_message_text("⚠️ 未找到用户信息，请确认是否已注册。")

    except Exception as e:
        print(f"[查询余额异常]: {e}")
        await query.edit_message_text("❌ 查询余额时发生错误，请稍后再试。")

async def handle_show_refcode_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    telegram_id = str(query.from_user.id)

    try:
        connection = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with connection:
            with connection.cursor() as cursor:
                cursor.execute(
                    "SELECT referred_code FROM users WHERE telegram_id = %s AND status = 1 LIMIT 1", 
                    (telegram_id,)
                )
                row = cursor.fetchone()
                if row and row['referred_code']:
                    await query.edit_message_text(f"📌 你的推荐码： `{row['referred_code']}`", parse_mode='Markdown')
                else:
                    await query.edit_message_text("⚠️ 未找到推荐码，请稍后再试。")
    except Exception as e:
        print(f"[查询推荐码异常]: {e}")
        await query.edit_message_text("❌ 查询推荐码时发生错误，请稍后再试。")


async def handle_show_games_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute("""
                    SELECT id, end_time 
                    FROM lob_game_logs
                    WHERE end_time IS NOT NULL
                    ORDER BY id DESC
                    LIMIT 5
                """)
                rows = cursor.fetchall()
                if rows:
                    lines = [f"🕹 游戏ID：{row['id']}，开奖时间：{row['end_time'].strftime('%Y-%m-%d %H:%M')}" for row in rows]
                    msg = "\n".join(lines) + "\n\n想查看具体局，请输入：查询 游戏ID"
                else:
                    msg = "⚠️ 暂无历史游戏记录"
        await query.edit_message_text(msg)
    except Exception as e:
        print(f"[查询最新游戏异常]: {e}")
        await query.edit_message_text("❌ 查询时发生错误，请稍后再试。")
    return



async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    global waiting_for_continue, betting, listening, awaiting_result, force_stop, highest_bid, highest_user, attempt, bet_min, bet_max, bets,wait_continue_task
    username = update.message.from_user.username
    text = update.message.text.strip()
    chat_id = update.message.chat.id

    print(f'[{datetime.now()}] {username}: {text}')

    # 如果正在等待庄家是否续庄
    if waiting_for_continue and username == waiting_for_continue and text.strip().lower() in ["是", "否"]:
        if wait_continue_task and not wait_continue_task.done():
            wait_continue_task.cancel()
            wait_continue_task = None
        banker_username = waiting_for_continue
        waiting_for_continue = None  # 清除等待状态

        if text.strip().lower() == "是":
            highest_bid = highest_bid  # 保留之前标桩
            highest_user = banker_username
            bet_min = max(1, int(highest_bid * bet_min_ratio))
            bet_max = max(1, int(highest_bid * bet_max_ratio))
            attempt = 1
            bets = {}
            betting = True
            listening = False
            awaiting_result = False
            force_stop = False
            await update.message.reply_text(f"✅ @{banker_username} 选择续庄，开始新一局！")
            await update.message.reply_text(f"进入下注环节（限时 {betDetectTime} 秒）：庄家：@{highest_user} 无需下注\n金额范围：{bet_min} ~ {bet_max}")
            asyncio.create_task(start_betting(chat_id, context))
        else:
            await update.message.reply_text(f"🔄 @{banker_username} 放弃续庄，开始新一轮标桩。")
            start_new_listening(context, chat_id)
        return

    if text == "查询":
        await update.message.reply_text("您可输入：查询 游戏ID 来查询您想要知道的游戏结果")

    if text == "我的id".strip().lower():
        telegram_id = str(update.message.from_user.id)
        await update.message.reply_text("您的ID是: ")
        await update.message.reply_text(telegram_id)
    
    # 查询具体游戏
    if text.startswith("查询 "):
        try:
            parts = text.split()
            if len(parts) == 2 and parts[1].isdigit():
                game_id = int(parts[1])
                conn = pymysql.connect(
                    host='localhost',
                    user='root',
                    password='31031992',
                    database='lobster_bet',
                    cursorclass=pymysql.cursors.DictCursor
                )
                with conn:
                    with conn.cursor() as cursor:
                        cursor.execute("""
                            SELECT * FROM lob_game_logs WHERE id = %s
                        """, (game_id,))
                        row = cursor.fetchone()
                        if row:
                            detail = row['detail'] if row['detail'] else '无明细'
                            msg = (
                                f"🔥 游戏 {row['id']} 局结果出炉 🔥\n"
                                "-----------------------------\n"
                                f"🏆 开奖结果：{row['result_number']}（{row['result']}）\n"
                                "-----------------------------\n"
                                f"游戏：{row['id']}\n"
                                f"开奖时间：{row['end_time'].strftime('%Y-%m-%d %H:%M:%S')}\n"
                                f"庄家：@{row['banker']}\n"
                                f"标桩金额：{row['banker_bid']}\n"
                                f"赔付：{row['total_paid']}                赢得：{row['total_win']}\n"
                                f"最后金额：{row['banker_after']}\n"
                                "-----------------------------\n"
                                f"{detail}\n"
                                "-----------------------------\n"
                                f"总实际赔付：{row['total_paid']}"
                            )
                        else:
                            msg = f"⚠️ 未找到游戏ID {game_id} 的记录"
                await update.message.reply_text(msg)
            else:
                await update.message.reply_text("⚠️ 格式错误，请输入：查询 游戏ID")
        except Exception as e:
            print(f"[查询具体游戏异常]: {e}")
            await update.message.reply_text("❌ 查询时发生错误，请稍后再试。")
        return




    if update.message.chat.type == 'private':
        telegram_id = update.message.from_user.id
        username = update.message.from_user.username

        reg_status = is_user_registered(telegram_id)
        if reg_status == True:
            keyboard = [
                [InlineKeyboardButton("查询余额", callback_data=f"check_balance_{telegram_id}")],
                [InlineKeyboardButton("查看推荐码", callback_data=f"show_refcode_{telegram_id}")],
                [InlineKeyboardButton("查询最新5局游戏结果", callback_data=f"show_games_{telegram_id}")]
            ]
            reply_markup = InlineKeyboardMarkup(keyboard)
            await update.message.reply_text("👋 你已经是注册用户，请选择：", reply_markup=reply_markup)
            return
        elif reg_status == "rejected":
            await update.message.reply_text("❌ 您的注册申请已被拒绝，如有问题请联系客服。")
            return
        else:
            keyboard = [[InlineKeyboardButton("注册", callback_data=f"register_{telegram_id}")]]
            reply_markup = InlineKeyboardMarkup(keyboard)
            await update.message.reply_text("您好！您还未注册，请点击下方按钮完成注册：", reply_markup=reply_markup)
            return  # 不继续后面的处理

    # 管理员指令
    if username == CONTROLLER:
        print(f'[{datetime.now()}] {username}: {text}')
        if text == "开始" and not listening and not betting:
            update_config_from_db()  # 📌 管理员说“开始”时加载配置
            listening = True
            force_stop = False
            highest_bid = 0
            highest_user = ""
            attempt = 1
            if update.message.chat.type in ['group', 'supergroup']:
                group_chat_id = chat_id  # ✅ 只记录群聊 ID
                print(group_chat_id)
            await update.message.reply_text(
                f"开始标桩！最低标桩为 {minBanker} 分，限时 {bankerDetectTime} 秒。（第 {attempt} 次）")
            asyncio.create_task(start_listening(chat_id, context))
            return
        elif text == "结束" and (listening or betting or awaiting_result):
            force_stop = True
            listening = betting = awaiting_result = False
            await update.message.reply_text("游戏已被管理员强制结束！")
            return

    # 标桩阶段
    if listening and username != BOT_USERNAME:
        try:
            number = int(text)
            if number >= minBanker:
                credit = get_user_credit(username)
                if number > credit:
                    await update.message.reply_text(f"⚠️ 你的余额不足，当前余额：{credit}")
                    return
            if highest_bid == 0 or number >= highest_bid + 100:
                highest_bid = number
                highest_user = username
                await update.message.reply_text(f"{username} 出价：{number}")
        except ValueError:
            pass

    # 下注阶段
    elif betting and username != highest_user and username != BOT_USERNAME:
        parts = text.split()
        if len(parts) != 2:
            await update.message.reply_text("格式错误，应为：种类 金额（如 单数 300）")
            return
        bet_type_raw, amount_str = parts
        bet_type = None
        if bet_type_raw in valid_types:
            bet_type = bet_type_raw
        else:
            match = re.match(r'^数字(\d+)$', bet_type_raw)
            if match:
                bet_type = f"数字{match.group(1)}"
        if not bet_type:
            await update.message.reply_text("下注种类无效，可用：单数、双数、大、小、数字X")
            return
        try:
            amount = int(amount_str)
            credit = get_user_credit(username)
            if amount > credit:
                await update.message.reply_text(f"⚠️ 你的余额不足，当前余额：{credit}")
                return
            if not (bet_min <= amount <= bet_max):
                await update.message.reply_text(f"金额需在 {bet_min} ~ {bet_max} 之间")
                return
        except ValueError:
            await update.message.reply_text("金额必须是数字")
            return
        # 记录下注：同用户同种类取更高
        user_bets = bets.get(username, [])
        updated = False
        for b in user_bets:
            if b['type'] == bet_type:
                if amount > b['amount']:
                    b['amount'] = amount
                updated = True
                break
        if not updated:
            user_bets.append({'type': bet_type, 'amount': amount})
        bets[username] = user_bets
        await update.message.reply_text(f"{username} 成功下注：{bet_type} {amount}")

    # 开奖阶段
    elif awaiting_result and username == CONTROLLER:
        try:
            number = int(text)
            if 1 <= number <= 10:
                awaiting_result = False
                final_result = number
                await update.message.reply_text(f"收到开奖结果：{number}，正在统计...")
                await process_result(number, context, chat_id)
            else:
                await update.message.reply_text("请输入 1~10 的数字作为开奖结果")
        except ValueError:
            await update.message.reply_text("请输入 1~10 的数字作为开奖结果")
    

async def start_listening(chat_id, context):
    global listening, highest_bid, highest_user, attempt, force_stop, bet_min, bet_max, betting, bets
    emojis = ['⚡️', '⏳', '🔥', '🐇', '🚀']
    try:
        await asyncio.sleep(bankerDetectTime - 5)
        file_id = 'CAACAgEAAyEFAASoMy7IAAIBjGhmKY2pJcLgcpVQCJOFMyyz0tJnAAJJBAAChO1ZRQZkvDRwD8xfNgQ'
        await context.bot.send_sticker(chat_id=chat_id, sticker=file_id)
        await asyncio.sleep(5)
    except asyncio.CancelledError:
        return

    if force_stop: return
    listening = False
    if highest_bid > 0:
        await context.bot.send_message(chat_id, text=f"时间到！最高标桩：{highest_bid} 分，由 @{highest_user} 出价。")
        bet_min = max(1, int(highest_bid * bet_min_ratio))
        bet_max = max(1, int(highest_bid * bet_max_ratio))
        betting = True
        bets = {}
        await context.bot.send_message(
            chat_id,
            text=f"进入下注环节（限时 {betDetectTime} 秒）：@{highest_user} 无需下注\n可下注：单数、双数、大、小、数字X\n金额范围：{bet_min} ~ {bet_max}")
        asyncio.create_task(start_betting(chat_id, context))
    else:
        if attempt < max_attempts:
            attempt += 1
            listening = True
            highest_bid = 0
            highest_user = ""
            await context.bot.send_message(chat_id, text=f"无人出价，自动重新开始（第 {attempt} 次）")
            asyncio.create_task(start_listening(chat_id, context))
        else:
            await context.bot.send_message(chat_id, text="无人出价，达到最大重试次数，游戏结束")

async def start_betting(chat_id, context):
    global betting, force_stop, awaiting_result, attempt, listening, highest_bid, highest_user,current_game_id
    emojis = ['⚡️', '⏳', '🔥', '🐇', '🚀']
    start_time = datetime.now()
    try:
        await asyncio.sleep(bankerDetectTime - 5)
        file_id = 'CAACAgEAAyEFAASoMy7IAAIBjGhmKY2pJcLgcpVQCJOFMyyz0tJnAAJJBAAChO1ZRQZkvDRwD8xfNgQ'
        await context.bot.send_sticker(chat_id=chat_id, sticker=file_id)
        await asyncio.sleep(5)
    except asyncio.CancelledError:
        return

    if force_stop: return
    betting = False
    if bets:
        summary = build_summary(start_time, datetime.now())
        awaiting_result = True
        await context.bot.send_message(chat_id, text=summary)
        await context.bot.send_message(chat_id, text="下注结束！请等待开奖结果，管理员请私聊我一个数字（1~10）")
        try:
            conn = pymysql.connect(
                host='localhost',
                user='root',
                password='31031992',
                database='lobster_bet',
                cursorclass=pymysql.cursors.DictCursor
            )
            with conn:
                with conn.cursor() as cursor:
                    total_amount = sum(b['amount'] for user_bets in bets.values() for b in user_bets)
                    user_count = len(bets)
                
                    # ✅ 写入 lob_game_logs 表，先拿到 game_id
                    cursor.execute(
                        "INSERT INTO lob_game_logs (start_time, banker, banker_bid, total_bets, user_count, detail) "
                        "VALUES (%s, %s, %s, %s, %s, %s)",
                        (
                            start_time.strftime('%Y-%m-%d %H:%M:%S'),
                            highest_user,
                            highest_bid,
                            total_amount,
                            user_count,
                            summary
                        )
                    )
                    current_game_id = cursor.lastrowid   # 拿到新插入行的 ID

                    # ✅ 写入 lob_game_bets 表
                    now_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    for username, user_bets in bets.items():
                        for b in user_bets:
                            cursor.execute(
                                "INSERT INTO lob_game_bets (game_id, username, bet_type, amount, create_time) "
                                "VALUES (%s, %s, %s, %s, %s)",
                                (current_game_id, username, b['type'], b['amount'], now_str)
                            )

                conn.commit()
            print("[✅ 游戏记录 & 下注明细已写入数据库]")
        except Exception as e:
            print(f"[写入游戏下注记录异常]: {e}")
    else:
        await context.bot.send_message(chat_id, text="无人下注。")
        if attempt < max_attempts:
            attempt += 1
            await context.bot.send_message(chat_id, text=f"重新开始标桩（第 {attempt} 次）")
            #global listening, highest_bid, highest_user
            listening = True
            highest_bid = 0
            highest_user = ""
            asyncio.create_task(start_listening(chat_id, context))
        else:
            await context.bot.send_message(chat_id, text="无人下注且已达到最大重试次数，游戏结束。")

def build_summary(start_time, end_time):
    global highest_user, highest_bid, bets
    type_counts = {'单数': set(), '双数': set(), '大': set(), '小': set(), '数字': set()}
    total_amount = 0
    user_count = len(bets)
    detail_lines = []
    for user, user_bets in bets.items():
        for b in user_bets:
            total_amount += b['amount']
            t = b['type']
            if t in type_counts:
                type_counts[t].add(user)
            elif t.startswith('数字'):
                type_counts['数字'].add(user)
            detail_lines.append(f"{user:<10} {t:<10} {b['amount']}")
    return (
        "-----------------------------\n"
        f"标桩结束：{start_time.strftime('%H:%M:%S')}\n下注结束：{end_time.strftime('%H:%M:%S')}\n"
        "-----------------------------\n"
        f"庄家：@{highest_user}\n金额：{highest_bid}\n"
        "-----------------------------\n"
        f"玩家人数：{user_count} 总金额：{total_amount}\n"
        f"单数下注：{len(type_counts['单数'])}\n"
        f"双数下注：{len(type_counts['双数'])}\n"
        f"大下注：{len(type_counts['大'])}\n"
        f"小下注：{len(type_counts['小'])}\n"
        f"数字下注：{len(type_counts['数字'])}\n"
        "-----------------------------\n"
        f"{'玩家':<10} {'下注':<10} 金额\n" + "\n".join(detail_lines)
    )

# 新增一个处理贴图的回调
async def handle_sticker(update, context):
    sticker = update.message.sticker
    if sticker:
        file_id = sticker.file_id
        print(f"收到贴图 file_id: {file_id}")
        # 你也可以回复用户
        await update.message.reply_text(f"贴图的 file_id 是：{file_id}")

async def process_result(number, context, chat_id):
    global bets, highest_user, highest_bid, group_chat_id, current_game_id
    result_type = {
        '单双': '单数' if number % 2 == 1 else '双数',
        '大小': '小' if number <= 4 else '大',
        '数字': f"数字{number}"
    }

    now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    total_bets = sum(b['amount'] for user_bets in bets.values() for b in user_bets)

    # 找到中奖用户
    winning_users = set()
    for user, user_bets in bets.items():
        for b in user_bets:
            if b['type'] == result_type['单双'] or b['type'] == result_type['大小'] or b['type'] == result_type['数字']:
                winning_users.add(user)
                break

    lose_bets = sum(
        sum(b['amount'] for b in user_bets) for user, user_bets in bets.items() if user not in winning_users
    )
    total_win = lose_bets

    # 应赔付列表
    win_list = []
    for user, user_bets in bets.items():
        for b in user_bets:
            payout = 0
            if b['type'] == result_type['单双'] or b['type'] == result_type['大小']:
                payout = int(b['amount'] * 1.9)
            elif b['type'] == result_type['数字']:
                payout = int(b['amount'] * 7)
            if payout > 0:
                win_list.append({'user': user, 'type': b['type'], 'bet': b['amount'], 'payout': payout})

    win_list.sort(key=lambda x: x['payout'], reverse=True)

    remain = highest_bid
    actual_payouts = []

    for win in win_list:
        actual = min(remain, win['payout'])
        if actual > 0:
            actual_payouts.append({
                'user': win['user'],
                'type': win['type'],
                'bet': win['bet'],
                'should_payout': win['payout'],
                'actual_payout': actual
            })
            remain -= actual
        if remain <= 0:
            break

    total_paid = sum(a['actual_payout'] for a in actual_payouts)
    banker_after = highest_bid + total_win - total_paid

    # === 新增：抽佣计算 ===
    commission_total = 0
    commission_banker = 0
    commission_players = 0

    if total_win > total_paid:
        # 庄家胜利
        profit = total_win - total_paid
        commission_banker = int(profit * 0.10)
        commission_total = commission_banker
        banker_after -= commission_banker
    elif total_paid > total_win:
        # 玩家胜利
        commission_players = int(total_paid * 0.10)
        commission_total = commission_players
        banker_after -= commission_players

        # 分摊到每个玩家
        total_actual_payout = sum(a['actual_payout'] for a in actual_payouts)
        for a in actual_payouts:
            user_commission = int(a['actual_payout'] / total_actual_payout * commission_players)
            a['commission'] = user_commission
    else:
        for a in actual_payouts:
            a['commission'] = 0

    # 无人中奖情况也补上
    if not actual_payouts:
        actual_payouts = []

    # detail
    if actual_payouts:
        lines = [
            f"@{a['user']} {a['type']} 中！下注：{a['bet']} 应得：{a['should_payout']} 实际赔付：{a['actual_payout']} 抽佣：{a.get('commission',0)}"
            for a in actual_payouts
        ]
        detail = "\n".join(lines)
    else:
        detail = "无人中奖"

    user_total_bets = {user: sum(b['amount'] for b in user_bets) for user, user_bets in bets.items()}

    # === 数据库 ===
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                # 玩家下注扣款
                for user, total_bet in user_total_bets.items():
                    cursor.execute("UPDATE users SET credit = credit - %s WHERE username = %s AND status = 1", (total_bet, user))

                # 发放赔付
                for a in actual_payouts:
                    cursor.execute("UPDATE users SET credit = credit + %s WHERE username = %s AND status = 1", (a['actual_payout'], a['user']))

                # 庄家结算加赢得金额 - 赔付
                profit = total_win - total_paid
                cursor.execute("UPDATE users SET credit = credit + %s WHERE username = %s AND status = 1", (profit, highest_user))

                # 抽佣扣除
                if commission_banker > 0:
                    cursor.execute("UPDATE users SET credit = credit - %s WHERE username = %s AND status = 1", (commission_banker, highest_user))
                elif commission_players > 0:
                    for a in actual_payouts:
                        if a.get('commission', 0) > 0:
                            cursor.execute("UPDATE users SET credit = credit - %s WHERE username = %s AND status = 1", (a['commission'], a['user']))

                # 更新游戏总记录
                cursor.execute("""
                    UPDATE lob_game_logs
                    SET 
                        end_time=%s,
                        total_bets=%s,
                        total_win=%s,
                        total_paid=%s,
                        banker_after=%s,
                        result_number=%s,
                        result=%s,
                        user_count=%s,
                        detail=%s,
                        commission_total=%s,
                        commission_banker=%s,
                        commission_players=%s
                    WHERE id=%s
                """, (
                    now_str,
                    total_bets,
                    total_win,
                    total_paid,
                    banker_after,
                    number,
                    f"{result_type['大小']}/{result_type['单双']}",
                    len(bets),
                    detail,
                    commission_total,
                    commission_banker,
                    commission_players,
                    current_game_id
                ))

                # 明细表
                for user, user_bets in bets.items():
                    for b in user_bets:
                        actual_payout = next((a['actual_payout'] for a in actual_payouts if a['user']==user and a['type']==b['type']), 0)
                        should_payout = next((a['should_payout'] for a in actual_payouts if a['user']==user and a['type']==b['type']), 0)
                        commission = next((a.get('commission',0) for a in actual_payouts if a['user']==user and a['type']==b['type']), 0)
                        cursor.execute("""
                            INSERT INTO lob_game_logs_detail
                            (game_id, username, bet_type, bet_amount, should_payout, actual_payout, commission)
                            VALUES (%s,%s,%s,%s,%s,%s,%s)
                        """, (current_game_id, user, b['type'], b['amount'], should_payout, actual_payout, commission))

            conn.commit()
    except Exception as e:
        print(f"[结算异常]: {e}")
        current_game_id = "N/A"

    # === 发消息 ===
    msg = (
        f"🔥 游戏 {current_game_id} 结果 🔥\n"
        f"开奖: {number}（{result_type['大小']}/{result_type['单双']}）\n"
        f"庄家: @{highest_user} 标桩: {highest_bid}\n"
        f"赔付: {total_paid} 赢得: {total_win}\n"
        f"抽佣: {commission_total}（庄家:{commission_banker} 玩家:{commission_players}）\n"
        f"结束余额: {banker_after}\n"
        f"总下注: {total_bets} 玩家数: {len(bets)}\n"
        f"{detail}"
    )
    await context.bot.send_message(chat_id, text=msg)
    if group_chat_id:
        await context.bot.send_message(group_chat_id, text=msg)

    # 查询余额
    msg2 = ""
    # 在发送消息前查询所有用户余额
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute("""
                    SELECT username, credit 
                    FROM users 
                    WHERE status = 1 AND type = 1 
                    ORDER BY credit DESC
                """)
                rows = cursor.fetchall()
                if rows:
                    balance_lines = ["\n👥 所有玩家当前余额\n------------\n"]
                    for row in rows:
                        balance_lines.append(f"@{row['username']}: {row['credit']:.2f}")
                    msg2 += "\n" + "\n".join(balance_lines)
    except Exception as e:
        print(f"[查询用户余额异常]: {e}")
        msg2 += "\n⚠️ 查询用户余额失败"
    await context.bot.send_message(chat_id, text=msg2)
    await ask_banker_continue(context, highest_user, highest_bid, chat_id)
    if group_chat_id:
        await context.bot.send_message(group_chat_id, text=msg2)
        await ask_banker_continue(context, highest_user, highest_bid, group_chat_id)


async def ask_banker_continue(context, banker_username, previous_bid, group_chat_id):
    global waiting_for_continue,wait_continue_task

    # 查询庄家当前余额
    try:
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='31031992',
            database='lobster_bet',
            cursorclass=pymysql.cursors.DictCursor
        )
        with conn:
            with conn.cursor() as cursor:
                cursor.execute("SELECT credit FROM users WHERE username=%s AND status=1 LIMIT 1", (banker_username,))
                row = cursor.fetchone()
                if not row:
                    print(f"[续庄] 未找到庄家用户：{banker_username}")
                    await context.bot.send_message(group_chat_id, "⚠️ 未找到庄家信息，开始新一轮标桩。")
                    start_new_listening(context, group_chat_id)
                    return
                credit = row['credit']
    except Exception as e:
        print(f"[续庄查询异常]: {e}")
        await context.bot.send_message(group_chat_id, "⚠️ 系统异常，开始新一轮标桩。")
        start_new_listening(context, group_chat_id)
        return

    if credit < previous_bid:
        await context.bot.send_message(group_chat_id, f"⚠️ @{banker_username} 当前余额不足（{credit:.2f} < {previous_bid}），开始新一轮标桩。")
        start_new_listening(context, group_chat_id)
        return

    # 余额足够，提醒庄家回复
    waiting_for_continue = banker_username
    await context.bot.send_message(group_chat_id, f"@{banker_username} 是否续庄？回复“是”继续，回复“否”则重新标桩。（30秒内回复）")

    # 启动一个30秒定时任务，如果超时还没回复就自动走新一轮
    wait_continue_task = asyncio.create_task(wait_continue_timeout(context, banker_username, group_chat_id, timeout=30))

async def wait_continue_timeout(context, banker_username, group_chat_id, timeout=30):
    global waiting_for_continue
    await asyncio.sleep(timeout)
    if waiting_for_continue == banker_username:
        waiting_for_continue = None
        await context.bot.send_message(group_chat_id, f"⌛ @{banker_username} 未在 {timeout} 秒内回复，开始新一轮标桩。")
        start_new_listening(context, group_chat_id)


def start_new_listening(context, chat_id):
    global listening, betting, awaiting_result, force_stop, highest_bid, highest_user, attempt, bets
    listening = True
    betting = False
    awaiting_result = False
    force_stop = False
    highest_bid = 0
    highest_user = ""
    attempt = 1
    bets = {}
    asyncio.create_task(start_listening(chat_id, context))



async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text('发送「开始」开始标桩，「结束」停止游戏。\n下注格式：种类 金额（如 单数 300）')

async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text('可下注：单数、双数、大、小、数字X\n例如：数字7 500')

async def error(update: Update, context: ContextTypes.DEFAULT_TYPE):
    print(f'Update {update} caused error {context.error}')

if __name__ == '__main__':
    print("Bot 正在运行中...")
    update_config_from_db()  # 第一次启动时也加载一次
    app = Application.builder().token(TOKEN).build()
    app.add_handler(CommandHandler('start', start_command))
    app.add_handler(CommandHandler('help', help_command))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

    # 注册按钮
    app.add_handler(CallbackQueryHandler(handle_register_callback, pattern=r'^register_\d+$'))

    # 查询余额按钮
    app.add_handler(CallbackQueryHandler(handle_check_balance_callback, pattern=r'^check_balance_\d+$'))

    # 查看推荐码按钮
    app.add_handler(CallbackQueryHandler(handle_show_refcode_callback, pattern=r'^show_refcode_\d+$'))

    # 查询最新5局游戏结果
    app.add_handler(CallbackQueryHandler(handle_show_games_callback, pattern=r'^show_games_\d+$'))

    app.add_error_handler(error)
    app.run_polling(poll_interval=3)
