# src/memorizz/llms/llm_provider.py

from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    List,
    Optional,
    Protocol,
    runtime_checkable,
)

# Use TYPE_CHECKING to handle forward references for type hints
if TYPE_CHECKING:
    pass

"""
A protocol in Python (introduced in PEP 544 and part of the typing module) defines a structural typing rule.
It specifies a set of methods and properties that a class must implement,
but it does not require inheritance.

"If it walks like a duck and quacks like a duck, it's probably a duck." 🦆

"""


@runtime_checkable
class LLMProvider(Protocol):
    """
    A generic protocol that defines the contract for any LLM provider
    to be compatible with both the OpenAI and AzureOpenAI classes.
    """

    # --- Attributes ---
    client: Any
    """Provides direct access to the underlying API client instance (e.g., openai.OpenAI or openai.AzureOpenAI)."""

    model: str
    """Stores the specific model or deployment name as a string (e.g., "gpt-4o")."""

    # --- Methods ---
    def get_tool_metadata(self, func: Callable) -> Dict[str, Any]:
        """Creates structured metadata (a JSON schema) from a Python function."""
        ...

    def augment_docstring(self, docstring: str) -> str:
        """Uses the LLM to enhance a function's docstring with more detail."""
        ...

    def generate_queries(self, docstring: str) -> List[str]:
        """Generates a list of example user queries for a given tool."""
        ...

    def generate_text(self, prompt: str, instructions: Optional[str] = None) -> str:
        """A high-level method for simple text generation."""
        ...

    def generate(
        self,
        messages: List[Dict[str, str]],
        tools: Optional[List[Dict[str, Any]]] = None,
        tool_choice: str = "auto",
    ) -> Any:
        """Generate a response from a list of messages (chat format), optionally with tool calling."""
        ...

    def get_config(self) -> Dict[str, Any]:
        """
        Returns a serializable dictionary of the provider's configuration.
        This is used for saving and reconstructing the agent.
        """
        ...

    def get_last_usage(self) -> Optional[Dict[str, int]]:
        """Return token usage details (prompt/completion/total) from the most recent call."""
        ...

    def get_context_window_tokens(self) -> Optional[int]:
        """Return the provider's context window size in tokens, when known."""
        ...
