"""账号绑定 handler"""
import asyncio
import logging
import re

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import ContextTypes, CommandHandler, MessageHandler, filters

from db.models import Action, GameScore
from services.bind_service import bind_with_email_token, unbind, get_binding
from services.message_utils import record_bot_message, safe_reply
from services.time_utils import format_dt
from services.game_service import get_scores_summary

logger = logging.getLogger("spam_guard")

EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")


async def cmd_bind(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """绑定授权账号。群内引导到私聊；私聊进入等待邮箱+Token 状态。"""
    user = update.effective_user
    logger.info(f"🔗 收到绑定指令: user={user.id}, chat_type={update.effective_chat.type}")
    existing = await get_binding(user.id)
    if existing:
        text = (
            "🔗 你已绑定授权账号\n"
            f"📧 邮箱: {existing.get('email') or existing.get('harvest_uid') or '-'}\n"
            f"⏳ 到期: {existing.get('time_expire') or '-'}\n"
            f"📅 绑定时间: {existing.get('bound_at')}\n\n"
            "如需重新绑定，先 /unbind"
        )
        reply = await safe_reply(update, context, text)
        asyncio.create_task(auto_delete(update.message, seconds=60))
        await record_bot_message(reply)
        asyncio.create_task(auto_delete(reply, seconds=60))
        return

    if update.effective_chat.type != "private":
        me = await context.bot.get_me()
        bot_username = me.username
        url = f"https://t.me/{bot_username}?start=bind"
        keyboard = InlineKeyboardMarkup([[InlineKeyboardButton("去私聊绑定", url=url)]])
        text = (
            "🔐 为了保护 Token，请到私聊完成绑定。\n\n"
            f"👉 点击进入：{url}"
        )
        try:
            reply = await safe_reply(update, context, text, reply_markup=keyboard, disable_web_page_preview=True)
        except Exception as e:
            logger.warning(f"🔗 绑定跳转按钮发送失败，改发普通文本: {type(e).__name__}: {e}")
            reply = await update.effective_chat.send_message(text, disable_web_page_preview=True)
        asyncio.create_task(auto_delete(update.message, seconds=60))
        await record_bot_message(reply)
        asyncio.create_task(auto_delete(reply, seconds=60))
        return

    context.user_data["awaiting_bind"] = True
    await safe_reply(update, context, 
        "🔐 授权绑定\n"
        "请发送邮箱和 Token，支持空格或换行分隔：\n\n"
        "邮箱 Token\n\n"
        "例如：user@example.com xxxxx"
    )


async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_chat.type == "private" and context.args and context.args[0] == "bind":
        await cmd_bind(update, context)


async def handle_private_bind_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_chat.type != "private" or not context.user_data.get("awaiting_bind"):
        return

    text = (update.message.text or "").strip()
    parts = text.replace("\n", " ").split()
    if len(parts) < 2:
        await safe_reply(update, context, "❌ 格式不对，请发送：邮箱 Token")
        return

    email, token = parts[0].strip(), parts[1].strip()
    if not EMAIL_RE.match(email):
        await safe_reply(update, context, "❌ 邮箱格式不正确，请重新发送：邮箱 Token")
        return

    processing = await safe_reply(update, context, "⏳ 正在验证授权信息...")
    ok, result = await bind_with_email_token(
        tg_user_id=update.effective_user.id,
        tg_username=update.effective_user.username or update.effective_user.first_name,
        email=email,
        token=token,
    )
    context.user_data["awaiting_bind"] = False

    try:
        await processing.delete()
    except Exception:
        pass

    if ok:
        data = result.get("data") or {}
        await Action.create(action="BIND", user_id=update.effective_user.id, username=update.effective_user.username, details={"email": data.get("email")})
        await safe_reply(update, context, 
            "✅ 绑定成功\n"
            f"📧 邮箱: {data.get('email') or email}\n"
            f"⏳ 到期: {data.get('time_expire') or '-'}"
        )
    else:
        context.user_data["awaiting_bind"] = True
        await safe_reply(update, context, f"❌ 验证失败：{result.get('msg') or result.get('reason') or '授权信息无效'}\n请重新发送：邮箱 Token")


async def cmd_me(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """查看当前 TG 用户绑定的授权信息和积分。"""
    user = update.effective_user
    binding = await get_binding(user.id)
    summary = await get_scores_summary(user.id)
    scores = summary["scores"]
    if scores:
        score_lines = []
        for item in scores:
            last = format_dt(item.last_played) if item.last_played else "未参与"
            score_lines.append(f"🎮 {item.game_type}: {item.score} 分｜次数 {item.total}｜连续 {item.streak}｜最近 {last}")
        checkin = summary["by_type"].get("checkin")
        trivia = summary["by_type"].get("trivia")
        checkin_text = "✅ 今日签到：已签到" if checkin and checkin.last_played and checkin.last_played.strftime("%Y-%m-%d") == __import__("datetime").datetime.now().strftime("%Y-%m-%d") else "✅ 今日签到：未签到"
        trivia_text = f"🎮 答题积分：{trivia.score} 分｜正确 {trivia.wins}/{trivia.total}｜连击 {trivia.streak}" if trivia else "🎮 答题积分：暂无"
        score_text = f"📊 总积分：{summary['total']} 分\n{checkin_text}\n{trivia_text}\n" + "\n".join(score_lines)
    else:
        score_text = "📊 积分：暂无记录\n✅ 今日签到：未签到\n🎮 答题积分：暂无\n💡 发送 /checkin 签到，或 /trivia 答题获取积分"

    if not binding:
        text = (
            "👤 我的账号\n"
            "━━━━━━━━━━━━━━━━━━━━\n"
            "🔗 授权状态：未绑定\n"
            f"{score_text}\n\n"
            "绑定授权后，我可以帮你查看授权邮箱和到期时间。\n"
            "请发送 /bind，然后按提示到私聊里提交邮箱和 Token。"
        )
    else:
        text = (
            "👤 我的账号\n"
            "━━━━━━━━━━━━━━━━━━━━\n"
            "🔗 授权状态：已绑定\n"
            f"📧 授权邮箱：{binding.get('email') or '-'}\n"
            f"⏳ 到期时间：{binding.get('time_expire') or '未返回'}\n"
            f"🕒 绑定时间：{format_dt(binding.get('bound_at')) or '-'}\n\n"
            f"{score_text}\n\n"
            "如需更换授权，请先 /unbind，再 /bind 重新绑定。"
        )
    reply = await safe_reply(update, context, text)
    if update.effective_chat.type != "private":
        asyncio.create_task(auto_delete(update.message, seconds=60))
        await record_bot_message(reply)
        asyncio.create_task(auto_delete(reply, seconds=60))


async def cmd_unbind(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """解绑 harvest 账号"""
    user = update.effective_user
    deleted = await unbind(user.id)
    if deleted:
        reply = await safe_reply(update, context, "🔓 已解除账号绑定")
        await Action.create(action="UNBIND", user_id=user.id, username=user.username)
    else:
        reply = await safe_reply(update, context, "❌ 你没有绑定的账号")
    asyncio.create_task(auto_delete(update.message, seconds=60))
    await record_bot_message(reply)
    asyncio.create_task(auto_delete(reply, seconds=60))


async def auto_delete(message, seconds=60):
    try:
        await asyncio.sleep(seconds)
        await message.delete()
    except Exception:
        pass


def register_bind(app):
    app.add_handler(CommandHandler("start", cmd_start, filters.ChatType.PRIVATE))
    app.add_handler(CommandHandler("bind", cmd_bind))
    app.add_handler(CommandHandler("me", cmd_me))
    app.add_handler(CommandHandler("unbind", cmd_unbind))
    app.add_handler(MessageHandler(filters.TEXT & filters.ChatType.PRIVATE & ~filters.COMMAND, handle_private_bind_text), group=0)
