import asyncio
import logging
from collections.abc import Callable, Coroutine

from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import ContextTypes

logger = logging.getLogger(__name__)

_pending_asks: dict[int, tuple[asyncio.Future[str], list[dict[str, str]]]] = {}


def make_ask_user_callback(
    user_id: int, bot: Bot, chat_id: int
) -> Callable[[str, list[dict[str, str]]], Coroutine[object, object, str]]:
    async def ask_user(question: str, options: list[dict[str, str]]) -> str:
        keyboard = InlineKeyboardMarkup(
            [
                [InlineKeyboardButton(opt["label"], callback_data=str(i))]
                for i, opt in enumerate(options)
            ]
        )
        await bot.send_message(chat_id=chat_id, text=question, reply_markup=keyboard)

        loop = asyncio.get_running_loop()
        future: asyncio.Future[str] = loop.create_future()
        _pending_asks[user_id] = (future, options)

        logger.info(
            "[ask_user] pergunta enviada para user_id=%d; pending_asks keys=%s",
            user_id,
            list(_pending_asks),
        )
        result = await future
        logger.info("[ask_user] future resolvida para user_id=%d com valor=%r", user_id, result)
        return result

    return ask_user


def resolve_pending_text_response(user_id: int, text: str) -> bool:
    entry = _pending_asks.pop(user_id, None)
    if entry is None:
        return False

    future, _options = entry
    if future.done():
        return True

    future.set_result(text)
    return True


async def handle_callback_query(update: Update, _context: ContextTypes.DEFAULT_TYPE) -> None:
    query = update.callback_query
    if query is None:
        return

    await query.answer()
    user_id = query.from_user.id

    logger.info(
        "[callback_query] recebido user_id=%d data=%r; pending_asks keys=%s",
        user_id,
        query.data,
        list(_pending_asks),
    )

    entry = _pending_asks.pop(user_id, None)
    if entry is None:
        logger.warning("[callback_query] nenhuma future pendente para user_id=%d", user_id)
        return

    future, options = entry
    if future.done():
        logger.warning("[callback_query] future já concluída para user_id=%d", user_id)
        return

    try:
        idx = int(query.data or "0")
        answer = options[idx]["label"]
    except (ValueError, IndexError):
        answer = str(query.data or "")

    future.set_result(answer)
    logger.info("[callback_query] future resolvida para user_id=%d com answer=%r", user_id, answer)
