"""Gemini embedding client — text-embedding-004. Singleton (persistent httpx pool).

Hatalar ExternalServiceError ile sarmalanır; ham hata client'a sızmaz.
Cache opsiyonel (Redis kapalıysa atlanır — [[env-setup]]).
"""
import hashlib
import json
import logging

import httpx

from app.cache import cache
from app.config import settings
from app.utils.exceptions import ExternalServiceError

logger = logging.getLogger("flovy")

EMBED_MODEL = "text-embedding-004"
_EMBED_CACHE_TTL = 3600


class EmbeddingClient:
    """DI ile enjekte edilen singleton — her istekte yeniden örneklenmez."""

    def __init__(self) -> None:
        self._client: httpx.AsyncClient | None = None

    def _http(self) -> httpx.AsyncClient:
        if self._client is None:
            self._client = httpx.AsyncClient(timeout=10.0)
        return self._client

    async def embed(self, text: str, task: str = "RETRIEVAL_DOCUMENT") -> list[float]:
        cache_key = f"flovy:emb:{hashlib.md5(text[:200].encode()).hexdigest()}:{task}"
        cached = await cache.get(cache_key)
        if cached:
            return json.loads(cached)

        if not settings.gemini_api_key:
            raise ExternalServiceError(
                "AI_NOT_CONFIGURED", "Embedding servisi yapılandırılmamış.", 503
            )

        url = f"{settings.gemma_endpoint}/models/{EMBED_MODEL}:embedContent"
        try:
            resp = await self._http().post(
                url,
                params={"key": settings.gemini_api_key},
                json={
                    "model": f"models/{EMBED_MODEL}",
                    "content": {"parts": [{"text": text}]},
                    "taskType": task,
                },
            )
            resp.raise_for_status()
            vec = resp.json()["embedding"]["values"]
        except httpx.TimeoutException as e:
            raise ExternalServiceError("AI_TIMEOUT", "Embedding servisi yanıt vermedi.", 503) from e
        except (httpx.HTTPStatusError, httpx.HTTPError, KeyError) as e:
            logger.error("Embedding API hata: %s", e)
            raise ExternalServiceError(
                "AI_ERROR", "Embedding servisi geçici olarak kullanılamıyor.", 503
            ) from e

        await cache.setex(cache_key, _EMBED_CACHE_TTL, json.dumps(vec))
        return vec

    async def aclose(self) -> None:
        if self._client is not None:
            await self._client.aclose()
            self._client = None


# Singleton + DI provider
_embedding_client = EmbeddingClient()


def get_embedding_client() -> EmbeddingClient:
    return _embedding_client
