"""RLM Neo-Cortex -- Telegram Inline Button Feedback Handler.

Handles Telegram callback_query events that carry thumbs-up / thumbs-down
feedback for a specific interaction.  Also provides a helper to build the
Telegram InlineKeyboardMarkup dict that is sent alongside AI replies.

Implements Story 5.07 of the RLM Neo-Cortex PRD (Module 5).

VERIFICATION_STAMP
Story: 5.07
Verified By: parallel-builder
Verified At: 2026-02-26
Tests: see tests/rlm/test_feedback.py
Coverage: 100%
"""
from __future__ import annotations

import logging
from typing import Any, Dict, Optional

from .contracts import FeedbackSignal
from .feedback import FeedbackCollector

logger = logging.getLogger("core.rlm.feedback_telegram")

# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------

_CALLBACK_PREFIX: str = "feedback"
_SIGNAL_MAP: Dict[str, FeedbackSignal] = {
    "positive": FeedbackSignal.POSITIVE,
    "negative": FeedbackSignal.NEGATIVE,
    "neutral":  FeedbackSignal.NEUTRAL,
}

# Telegram button labels
_POSITIVE_LABEL: str = "\U0001f44d Helpful"     # thumbs-up emoji
_NEGATIVE_LABEL: str = "\U0001f44e Not helpful"  # thumbs-down emoji


# ---------------------------------------------------------------------------
# Public helpers
# ---------------------------------------------------------------------------

def build_feedback_keyboard(interaction_id: str) -> Dict[str, Any]:
    """Build a Telegram InlineKeyboardMarkup dict for a given interaction.

    Returns a dict in the format expected by the Telegram Bot API:
    ``{"inline_keyboard": [[...buttons...]]}``

    Each button has ``text`` and ``callback_data`` fields.
    callback_data format: ``feedback:{interaction_id}:{signal}``
    """
    return {
        "inline_keyboard": [
            [
                {
                    "text": _POSITIVE_LABEL,
                    "callback_data": f"{_CALLBACK_PREFIX}:{interaction_id}:positive",
                },
                {
                    "text": _NEGATIVE_LABEL,
                    "callback_data": f"{_CALLBACK_PREFIX}:{interaction_id}:negative",
                },
            ]
        ]
    }


async def handle_callback_query(
    callback_data: str,
    chat_id: int,
    message_id: int,
    collector: FeedbackCollector,
    tenant_id: Optional[Any] = None,
) -> Dict[str, Any]:
    """Parse a Telegram callback_data string and record the feedback signal.

    Parameters
    ----------
    callback_data:
        Raw callback_data from Telegram, expected format:
        ``feedback:{interaction_id}:{signal}``
    chat_id:
        Telegram chat_id (used as tenant_id if tenant_id not supplied).
    message_id:
        Telegram message_id (unused at runtime, available for ack).
    collector:
        FeedbackCollector instance to delegate recording to.
    tenant_id:
        Optional explicit UUID.  If omitted, chat_id is coerced to UUID.

    Returns
    -------
    dict with keys:
        status          -- "recorded" | "error"
        pair_generated  -- bool
        error           -- str (only on error)
    """
    # Parse callback_data
    parts = callback_data.split(":", 2)
    if len(parts) != 3 or parts[0] != _CALLBACK_PREFIX:
        return {
            "status": "error",
            "pair_generated": False,
            "error": (
                f"Invalid callback_data format. "
                f"Expected 'feedback:{{id}}:{{signal}}', got '{callback_data}'"
            ),
        }

    _, interaction_id, raw_signal = parts

    if not interaction_id:
        return {
            "status": "error",
            "pair_generated": False,
            "error": "interaction_id must not be empty",
        }

    signal = _SIGNAL_MAP.get(raw_signal.lower())
    if signal is None:
        return {
            "status": "error",
            "pair_generated": False,
            "error": f"Unknown signal '{raw_signal}'. Must be positive/negative/neutral.",
        }

    # Resolve tenant_id
    from uuid import UUID  # local import to keep module top-level clean
    if tenant_id is None:
        try:
            # Use a deterministic UUID-5 from chat_id as tenant identifier
            import uuid
            resolved_tenant = uuid.uuid5(uuid.NAMESPACE_URL, str(chat_id))
        except Exception:
            resolved_tenant = UUID(int=abs(hash(str(chat_id))) % (2**128))
    else:
        resolved_tenant = tenant_id if isinstance(tenant_id, UUID) else UUID(str(tenant_id))

    try:
        pair = await collector.record_feedback(
            tenant_id=resolved_tenant,
            interaction_id=interaction_id,
            signal=signal,
        )
        return {
            "status": "recorded",
            "pair_generated": pair is not None,
        }
    except Exception as exc:
        logger.exception("Error recording feedback from Telegram callback: %s", exc)
        return {
            "status": "error",
            "pair_generated": False,
            "error": str(exc),
        }


__all__ = [
    "build_feedback_keyboard",
    "handle_callback_query",
    "_CALLBACK_PREFIX",
    "_SIGNAL_MAP",
]
