from __future__ import annotations

from .base import (
    BaseProvider,
    JsonDict,
    ProviderError,
    build_gemini_contents,
    build_gemini_tools,
    ensure_trailing_slashless,
    extract_gemini_model_names,
    gemini_system_instruction,
    normalise_gemini_response,
    with_query_params,
)


class GeminiProvider(BaseProvider):
    provider_type = "gemini"

    def __init__(
        self,
        *,
        api_key: str,
        base_url: str = "https://generativelanguage.googleapis.com/v1beta",
        provider_name: str = "gemini",
        timeout: float = 60.0,
        http_client=None,
    ) -> None:
        super().__init__(provider_name=provider_name, timeout=timeout, http_client=http_client)
        self.api_key = api_key
        self.base_url = ensure_trailing_slashless(base_url)

    def _ensure_configured(self) -> None:
        if not self.api_key:
            raise ProviderError("gemini requires an API key. Configure it via Telegram /settings or /apikey gemini <key>.")

    async def generate(
        self,
        messages: list[JsonDict],
        tools: list[JsonDict] | None,
        model: str,
        system_prompt: str | None = None,
        temperature: float | None = None,
    ) -> JsonDict:
        self._ensure_configured()
        payload: JsonDict = {"contents": build_gemini_contents(messages)}
        tool_block = build_gemini_tools(tools)
        if tool_block:
            payload["tools"] = tool_block
        system_instruction = gemini_system_instruction(system_prompt)
        if system_instruction:
            payload["systemInstruction"] = system_instruction
        if temperature is not None:
            payload["generationConfig"] = {"temperature": temperature}

        url = with_query_params(f"{self.base_url}/models/{model}:generateContent", key=self.api_key)
        response = await self.http.post_json(url, payload=payload)
        return normalise_gemini_response(response.payload, fallback_model=model, provider_name=self.provider_name)

    async def list_models(self) -> list[str]:
        self._ensure_configured()
        url = with_query_params(f"{self.base_url}/models", key=self.api_key)
        response = await self.http.get_json(url)
        return extract_gemini_model_names(response.payload)
