"""LLM client protocol for provider abstraction.

Defines the structural interface that both OllamaClient and VLLMClient
must satisfy, using typing.Protocol for duck-typing compatibility.

Requirements: 1.1, 1.2
"""
from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, runtime_checkable

if TYPE_CHECKING:
    from services.extractor.client import ExtractionAttempt


@runtime_checkable
class LLMClient(Protocol):
    """Protocol defining the contract for LLM inference clients.

    Both OllamaClient and VLLMClient satisfy this protocol via
    structural subtyping — no inheritance required.
    """

    async def call_llm(
        self,
        prompts: dict[str, str],
        json_schema: dict[str, object],
        document_text: str = "",
    ) -> ExtractionAttempt:
        """Send a chat completion request and return an extraction attempt.

        Args:
            prompts: Dict with 'system' and 'user' prompt strings.
            json_schema: JSON schema hint for structured output.
            document_text: Optional raw document text for context.

        Returns:
            An ExtractionAttempt with raw output, validation, and error info.
        """
        ...

    async def close(self) -> None:
        """Release underlying HTTP resources."""
        ...
