from __future__ import annotations

import asyncio
import logging
from collections.abc import Awaitable, Callable
from datetime import date

from checkin_cli.nutrition_onboarding_contract import QUESTION_FIELDS

from gateway.platforms.nutrition_onboarding_reconciliation import (
    NutritionOnboardingClarification,
)
from gateway.platforms.nutrition_onboarding_reconciliation_copy import (
    render_clarification_text,
)
from gateway.platforms.telegram_nutrition_onboarding_preview_completion import (
    log_clarification_receipt,
    send_preview_card,
)
from gateway.platforms.telegram_nutrition_onboarding_preview_types import (
    PreviewRoute,
    PreviewSession,
)


logger = logging.getLogger(__name__)


class TelegramNutritionOnboardingPreviewPublicationMixin:
    _sender: Callable[
        [PreviewRoute, str, bool, str | None, str | None],
        Awaitable[object],
    ]
    _lock: asyncio.Lock
    _session: PreviewSession | None

    def purge(self) -> None:
        raise NotImplementedError

    def _arm_expiry(self) -> None:
        raise NotImplementedError

    async def _publish_clarification(
        self,
        message: object,
        route: PreviewRoute,
        answers: tuple[tuple[str, object], ...],
        clarifications: tuple[NutritionOnboardingClarification, ...],
        cursor: int,
        *,
        reference_date: date | None = None,
    ) -> None:
        item = clarifications[cursor]
        text = render_clarification_text(
            item,
            index=cursor + 1,
            total=len(clarifications),
        )
        receipt = await send_preview_card(
            self._sender,
            route,
            f"[PREVIEW][NUTRITION ONBOARDING]\n{text}",
            True,
            str(getattr(message, "message_id", "") or ""),
            None,
        )
        receipt_id = str(getattr(receipt, "message_id", "") or "")
        if not receipt_id:
            self.purge()
            return
        if reference_date is None:
            if self._session is None:
                raise RuntimeError("preview reference date is unavailable")
            reference_date = self._session.reference_date
        self._session = PreviewSession(
            len(QUESTION_FIELDS),
            receipt_id,
            answers,
            reference_date,
            "clarifying",
            clarifications,
            cursor,
        )
        log_clarification_receipt(
            route,
            message_id=receipt_id,
            field=item.field,
        )
        self._arm_expiry()

    async def _publish_summary(
        self,
        message: object,
        route: PreviewRoute,
        text: str,
        *,
        reference_date: date | None = None,
    ) -> None:
        if reference_date is None:
            if self._session is None:
                raise RuntimeError("preview reference date is unavailable")
            reference_date = self._session.reference_date
        self._session = None
        receipt = await send_preview_card(
            self._sender,
            route,
            f"[PREVIEW][NUTRITION ONBOARDING]\n{text}",
            False,
            None,
            "confirm",
        )
        receipt_id = str(getattr(receipt, "message_id", "") or "")
        if not receipt_id:
            self.purge()
            return
        self._session = PreviewSession(
            len(QUESTION_FIELDS),
            receipt_id,
            (),
            reference_date,
            "confirming",
        )
        logger.warning(
            "Nutrition onboarding preview summary published: "
            "chat=%s topic=%s message_id=%s",
            route.chat_id,
            route.topic_id,
            receipt_id,
        )
        self._arm_expiry()
