"""ToolContext and CallerInfo — injected into every tool handler."""
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass(frozen=True)
class CallerInfo:
    """Identity and channel metadata for the user who triggered the tool call."""

    channel: str
    channel_user_id: str | None = None
    external_user_id: str | None = None
    email: str | None = None
    display_name: str | None = None


@dataclass(frozen=True)
class ToolContext:
    """Per-call context injected into tool handler functions.

    Provides caller identity, conversation metadata, and convenience helpers.
    """

    caller: CallerInfo
    conversation_id: str
    call_id: str
    product_id: str | None = None
    confirmed: bool = False

    @property
    def is_identified(self) -> bool:
        """True when the caller has a resolved external user ID."""
        return self.caller.external_user_id is not None

    @classmethod
    def from_payload(cls, payload: dict[str, Any]) -> ToolContext:
        """Construct a ``ToolContext`` from a raw webhook payload dict."""
        caller_data = payload.get("caller") or {}
        caller = CallerInfo(
            channel=caller_data.get("channel", "web"),
            channel_user_id=caller_data.get("channel_user_id"),
            external_user_id=caller_data.get("external_user_id"),
            email=caller_data.get("email"),
            display_name=caller_data.get("display_name"),
        )
        return cls(
            caller=caller,
            conversation_id=payload.get("conversation_id", ""),
            call_id=payload.get("call_id", ""),
            product_id=payload.get("product_id"),
            confirmed=bool(payload.get("confirmed")),
        )
