"""Pre-checkout query auto-answer context manager."""

import logging
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from aiogram.types import PreCheckoutQuery
    from ui_router.state.context import ExecutionContext

logger = logging.getLogger(__name__)


class PreCheckoutState:
    """Состояние ответа на pre_checkout_query.

    Бизнес-логика через context.event_data["pre_checkout_state"]
    может вызвать:
    - await state.answer_ok()  — немедленно одобрить (не ждать конца actions)
    - await state.answer_fail("причина") — немедленно отклонить

    Если ни один метод не вызван — auto ok=True при выходе из scope.
    """

    __slots__ = ("_answered", "_event", "error_message", "ok")

    def __init__(self, event: "PreCheckoutQuery") -> None:
        self.ok: bool = True
        self.error_message: str | None = None
        self._answered: bool = False
        self._event = event

    def decline(self, reason: str) -> None:
        """Пометить платёж для отклонения (ответ отправится при выходе из scope)."""
        self.ok = False
        self.error_message = reason

    async def answer_ok(self) -> None:
        """Немедленно ответить ok=True. Не ждать завершения actions."""
        if self._answered:
            return
        self.ok = True
        self.error_message = None
        self._answered = True
        await self._event.answer(ok=True)
        logger.debug("Pre-checkout query answered immediately: ok=True")

    async def answer_fail(self, reason: str) -> None:
        """Немедленно ответить ok=False с причиной."""
        if self._answered:
            return
        self.ok = False
        self.error_message = reason
        self._answered = True
        await self._event.answer(ok=False, error_message=reason)
        logger.debug("Pre-checkout query answered immediately: ok=False, error=%s", reason)


@asynccontextmanager
async def pre_checkout_scope(
    event: "PreCheckoutQuery", context: "ExecutionContext",
) -> AsyncIterator[PreCheckoutState]:
    """Контекстный менеджер для auto-answer pre_checkout_query.

    Использование в handler:
        async with pre_checkout_scope(event, context):
            await handler_service.process_global_handler(handler, event, context)

    Бизнес-action внутри может:
        state = context.event_data["pre_checkout_state"]

        # Вариант 1: немедленный ответ (рекомендуется)
        await state.answer_ok()    # одобрить сразу, actions продолжат работу
        await state.answer_fail("Товар закончился")  # отклонить сразу

        # Вариант 2: отложенный ответ (при выходе из scope)
        state.decline("Цена изменилась")  # ответ отправится после всех actions

    Если ничего не вызвано — автоматический answer(ok=True) при выходе.

    Yields:
        PreCheckoutState: State object for controlling the pre-checkout response.
    """
    state = PreCheckoutState(event)
    context.event_data["pre_checkout_state"] = state

    try:
        yield state
    finally:
        if not state._answered:
            state._answered = True
            try:
                await event.answer(ok=state.ok, error_message=state.error_message)
                logger.debug(
                    "Pre-checkout query auto-answered: ok=%s, error=%s",
                    state.ok,
                    state.error_message,
                )
            except Exception:
                logger.exception("Failed to answer pre_checkout_query")
