import openai

from .base import LLMProvider
from .json_utils import parse_json_response


class OpenAICompatibleProvider(LLMProvider):
    """Handles OpenAI's own API and any OpenAI-compatible endpoint (Ollama, vLLM,
    Groq, etc.) - they share the same request/response wire format, so one class
    covers both; only api_key/base_url/model differ, which is exactly how
    goplaces_backend/v4/agent.py toggled between cloud OpenAI and local Ollama.
    """

    def __init__(
        self,
        api_key: str | None,
        model: str,
        base_url: str | None = None,
        use_json_mode: bool = True,
    ) -> None:
        self.client = openai.OpenAI(api_key=api_key, base_url=base_url)
        self.model = model
        # Local/Ollama models generally don't honour response_format=json_object
        # reliably, so that mode is opt-out for them; the system prompt + the
        # tolerant parser in json_utils carry the JSON-only contract instead.
        self.use_json_mode = use_json_mode

    def complete_json(self, system_prompt: str, messages: list[dict]) -> dict:
        chat_messages = [{"role": "system", "content": system_prompt}, *messages]
        kwargs = {"response_format": {"type": "json_object"}} if self.use_json_mode else {}
        response = self.client.chat.completions.create(
            model=self.model,
            messages=chat_messages,
            **kwargs,
        )
        return parse_json_response(response.choices[0].message.content)
