"""
텔레그램 봇 폴링 서비스
- 백그라운드에서 텔레그램 봇의 업데이트를 폴링
- 인라인 버튼 클릭 처리 (가입 승인/거부)
"""

import logging
from typing import Optional

from telegram import Update
from telegram.ext import Application, CallbackQueryHandler, ContextTypes
from flask import Flask

from backend.models.telegram_bot import TelegramBot
from backend.models.user import User, db

logger = logging.getLogger(__name__)


async def handle_approval_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """
    텔레그램 인라인 버튼 클릭 처리
    callback_data 형식: "approve_{token}" 또는 "reject_{token}"
    """
    query = update.callback_query
    await query.answer()

    data = query.data or ""
    logger.info("Received callback: %s", data)

    # Flask app 객체는 bot_data에 저장해둔 것을 사용
    flask_app: Optional[Flask] = context.application.bot_data.get("flask_app")

    if flask_app is None:
        logger.error("Flask app context is missing in bot_data")
        await query.edit_message_text(
            text="❌ 내부 설정 오류로 요청을 처리할 수 없습니다. 관리자에게 문의해 주세요."
        )
        return

    # callback_data 형식 검증
    if "_" not in data:
        logger.warning("Invalid callback data format: %s", data)
        await query.edit_message_text(
            text="❌ 유효하지 않은 요청입니다."
        )
        return

    try:
        action, token = data.split("_", 1)
    except ValueError:
        logger.warning("Failed to split callback data: %s", data)
        await query.edit_message_text(
            text="❌ 유효하지 않은 요청입니다."
        )
        return

    try:
        with flask_app.app_context():
            # 토큰으로 사용자 찾기
            user = User.query.filter_by(approval_token=token).first()

            if not user:
                await query.edit_message_text(
                    text="❌ 유효하지 않은 승인 요청입니다.\n(이미 처리되었거나 만료된 요청)"
                )
                return

            if action == "approve":
                # 승인 처리
                user.is_approved = True
                user.is_active = True
                user.approval_token = None  # 토큰 무효화

                db.session.commit()

                await query.edit_message_text(
                    text=(
                        "✅ 승인 완료!\n\n"
                        f"👤 사용자: {user.username}\n"
                        f"📧 이메일: {user.email}\n\n"
                        "사용자가 이제 로그인할 수 있습니다."
                    )
                )
                logger.info("User %s approved", user.username)

            elif action == "reject":
                # 거부 처리 - 사용자 삭제
                username = user.username
                email = user.email

                db.session.delete(user)
                db.session.commit()

                await query.edit_message_text(
                    text=(
                        "❌ 가입 거부됨\n\n"
                        f"👤 사용자: {username}\n"
                        f"📧 이메일: {email}\n\n"
                        "계정이 삭제되었습니다."
                    )
                )
                logger.info("User %s rejected and deleted", username)
            else:
                logger.warning("Unknown action in callback: %s", action)
                await query.edit_message_text(
                    text="❌ 유효하지 않은 요청입니다."
                )

    except Exception as e:
        logger.exception("Error handling callback: %s", e)
        # 예외 내용은 사용자에게 직접 노출하지 않음
        try:
            db.session.rollback()
        except Exception:
            logger.exception("DB rollback failed")

        await query.edit_message_text(
            text="❌ 요청 처리 중 오류가 발생했습니다. 잠시 후 다시 시도하거나 관리자에게 문의해 주세요."
        )


def run_polling(flask_app: Flask) -> None:
    """
    동기 함수: 백그라운드 스레드에서 직접 호출됨
    Application.run_polling() 이 내부에서 asyncio 이벤트 루프를 관리하므로
    여기서는 asyncio.run 을 사용하지 않는다.
    """
    if flask_app is None:
        raise ValueError("flask_app is required for run_polling")

    # DB에서 활성 봇 조회
    with flask_app.app_context():
        bots = TelegramBot.query.filter_by(is_active=True).all()

        if not bots:
            logger.warning("No active bots found")
            return

        # 첫 번째 활성 봇만 사용 (여러 봇이 동시에 폴링하면 충돌 가능)
        bot = bots[0]
        flask_app.logger.info("Starting polling for bot: %s (ID: %s)", bot.name, bot.id)

    # Application 생성
    application = Application.builder().token(bot.token).build()

    # Flask app을 bot_data에 넣어서 핸들러에서 사용할 수 있게 함
    application.bot_data["flask_app"] = flask_app

    # 콜백 쿼리 핸들러 등록
    application.add_handler(CallbackQueryHandler(handle_approval_callback))

    try:
        # v20 스타일: run_polling 은 동기 함수이고, 내부에서 이벤트 루프를 직접 관리함
        application.run_polling(drop_pending_updates=True)
    except Exception as e:
        flask_app.logger.exception("Error in bot polling: %s", e)