"""Pillar backend SDK — register server-side tools and handle tool calls.

Quick start::

    from pillar import Pillar, ToolContext

    pillar = Pillar(secret="plr_...")

    @pillar.tool(description="Look up a customer by email")
    async def lookup_customer(email: str, ctx: ToolContext) -> dict:
        customer = await db.get_customer(email=email)
        return {"name": customer.name, "plan": customer.plan}
"""
from __future__ import annotations

import sys
from typing import Any, TypedDict

if sys.version_info >= (3, 11):
    from typing import Required
else:
    from typing_extensions import Required

from pillar._client import Pillar
from pillar._context import CallerInfo, ToolContext
from pillar._errors import (
    PillarError,
    RegistrationError,
    SignatureVerificationError,
    ToolNotFoundError,
)
from pillar._signature import verify_webhook_signature
from pillar._skill import SkillDefinition, define_skill


class ConfirmationResponse(TypedDict, total=False):
    """Standard shape for a confirmation response returned by a tool handler.

    Return this from your tool handler when the user should confirm before
    the action is performed. Pillar will render a channel-appropriate
    confirmation UI and re-call your handler with ``ctx.confirmed = True``
    after the user confirms.
    """

    confirmation_required: Required[bool]
    title: str
    message: str
    details: dict[str, str]
    confirm_payload: dict[str, Any]


class ToolResultAction(TypedDict, total=False):
    """A client-side action to render alongside the tool result.

    Currently supports ``open_url`` which is rendered as a clickable link
    in Slack or a navigation action in the web SDK.
    """

    type: Required[str]
    label: str
    url: str


class ToolResult(TypedDict, total=False):
    """Optional structured shape for a tool result after confirmation.

    Return this from your tool handler on the confirmed path
    (``ctx.confirmed == True``) to control how the result is displayed
    across channels (Slack, web, etc.).  All fields are optional —
    if omitted, the raw return value is shown as JSON.

    Example::

        @pillar.tool(description="Create a billing plan")
        async def create_plan(name: str, ctx: ToolContext) -> dict:
            if not ctx.confirmed:
                return ConfirmationResponse(...)
            plan = await billing.create(name)
            return {
                "summary": f"Created plan {plan.name}.",
                "data": {"id": plan.id, "name": plan.name},
                "actions": [
                    {"type": "open_url", "label": "View plan", "url": plan.url},
                ],
            }
    """

    summary: str
    data: dict[str, Any]
    actions: list[ToolResultAction]


__all__ = [
    "CallerInfo",
    "ConfirmationResponse",
    "Pillar",
    "PillarError",
    "RegistrationError",
    "SignatureVerificationError",
    "SkillDefinition",
    "ToolContext",
    "ToolNotFoundError",
    "ToolResult",
    "ToolResultAction",
    "define_skill",
    "verify_webhook_signature",
]

__version__ = "0.2.4"
