"""Ollama local AI provider — OpenAI-compatible API.

Ollama exposes an OpenAI-compatible endpoint at http://localhost:11434/v1.
No API key is required.  Works offline with models installed via `ollama pull`.

Usage:
    provider = OllamaProvider(base_url="http://localhost:11434/v1")
    response = provider.ask(AIRequest(prompt="Hello", model="llama3.2"))

Model discovery:
    Use list_models(base_url) to query models installed in the running instance.
"""

from __future__ import annotations

import json
import logging
import threading
import urllib.error
import urllib.request

import openai

from .base import AIProvider
from .base_provider import BaseAPIProvider

log = logging.getLogger(__name__)

DEFAULT_BASE_URL = "http://localhost:11434/v1"


def list_models(base_url: str = DEFAULT_BASE_URL, timeout: float = 5.0) -> list[str]:
    """Return model names installed in the Ollama instance.

    Calls GET <root>/api/tags  (note: NOT the /v1 path).

    Args:
        base_url: The Ollama base URL, e.g. "http://localhost:11434/v1".
                  The /v1 suffix is stripped automatically.
        timeout:  HTTP request timeout in seconds.

    Returns:
        List of model name strings, or [] if Ollama is unreachable.
    """
    # Strip /v1 or /v1/ suffix to reach the Ollama root
    root = base_url.rstrip("/")
    if root.endswith("/v1"):
        root = root[:-3]

    url = f"{root}/api/tags"
    try:
        req = urllib.request.Request(url, headers={"Accept": "application/json"})
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            data = json.loads(resp.read().decode("utf-8"))
        models = [m["name"] for m in data.get("models", [])]
        log.debug("Ollama: found %d models at %s", len(models), url)
        return models
    except urllib.error.URLError as exc:
        log.warning("Ollama: server not reachable at %s: %s", url, exc)
        return []
    except Exception as exc:
        log.warning("Ollama list_models error (%s): %s", url, exc)
        return []


class OllamaProvider(BaseAPIProvider, AIProvider):
    """Local Ollama provider using the OpenAI-compatible /v1 endpoint.

    Unlike cloud providers, Ollama requires no API key and is always
    considered «available» — errors surface at request time.

    Inherits ask(), stream(), _build_messages() from BaseAPIProvider.
    """

    name = "ollama"
    DEFAULT_MODEL = "llama3.2"

    def __init__(self, base_url: str = DEFAULT_BASE_URL) -> None:
        # Skip BaseAPIProvider.__init__ (no API key resolution needed)
        self._base_url = base_url.rstrip("/")
        self._client: openai.OpenAI | None = None
        self._client_lock = threading.Lock()
        self.api_key = ""  # no key needed

    def is_available(self) -> bool:
        """Ollama is always treated as available; errors appear at call time."""
        return True

    def _create_client(self) -> openai.OpenAI:
        # Ensure Ollama is running before creating the client
        try:
            from ..seb.ollama_guard import ensure_ollama_running
            ensure_ollama_running()
        except Exception as exc:
            log.warning("Ollama auto-start check failed: %s", exc)

        return openai.OpenAI(
            api_key="ollama",  # Ollama ignores the key field
            base_url=self._base_url,
            timeout=120.0,  # local models can be slow on first run
        )
