"""Shared tool and tool-call type definitions for LLM function calling (P0-0).

These types implement the OpenAI-compatible tool/function-calling interface so that
any provider whose gateway supports the spec (DeepSeek, Qwen, etc.) can expose
tools to the LLM and receive structured tool invocations in return.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class ToolCall:
    """Represent a single tool invocation returned by the LLM.

    The model fills in ``id``, ``name``, and ``arguments`` when it decides to call
    a tool instead of (or in addition to) producing a text response.
    """

    # Unique identifier assigned by the model for this call.
    id: str
    # Name of the tool to invoke, matching the name registered in Tool.
    name: str
    # Parsed JSON arguments ready for direct use by the tool handler.
    arguments: dict[str, Any] = field(default_factory=dict)


@dataclass
class ToolParameter:
    """JSON-Schema–compatible parameter block for a tool definition."""

    # Top-level schema type — always "object" for OpenAI-compatible tools.
    type: str = "object"
    # Map of parameter name → JSON-Schema property descriptor.
    properties: dict[str, Any] = field(default_factory=dict)
    # List of required parameter names.
    required: list[str] = field(default_factory=list)


@dataclass
class Tool:
    """Describe a callable tool that can be offered to the LLM.

    Example usage::

        search_tool = Tool(
            name="search_regulations",
            description="Search the compliance knowledge base for relevant regulation clauses.",
            parameters=ToolParameter(
                properties={"query": {"type": "string", "description": "Search query"}},
                required=["query"],
            ),
        )
        response = client.chat(messages, tools=[search_tool])
    """

    name: str
    description: str
    parameters: ToolParameter = field(default_factory=ToolParameter)

    def to_openai_format(self) -> dict[str, Any]:
        """Serialise this tool to the OpenAI-compatible function-calling schema.

        The returned dict can be placed directly in the ``tools`` list of a chat
        completions request without any further transformation.
        """
        return {
            "type": "function",
            "function": {
                "name": self.name,
                "description": self.description,
                "parameters": {
                    "type": self.parameters.type,
                    "properties": self.parameters.properties,
                    "required": self.parameters.required,
                },
            },
        }
