"""Embedding generation for Sulci."""

import logging

import httpx
from openai import AsyncOpenAI

from sulci_core.config import SulciConfig

logger = logging.getLogger(__name__)

VOYAGE_API_URL = "https://api.voyageai.com/v1/embeddings"


class EmbeddingGenerator:
    """Generate embeddings using OpenAI or Voyage AI."""

    def __init__(self, config: SulciConfig) -> None:
        self.config = config
        self._provider = config.effective_embedding_provider
        self._model = config.effective_embedding_model
        self._dimensions = config.embedding_dimensions

        if self._provider == "voyage":
            api_key = config.voyage_api_key
            if not api_key:
                logger.warning(
                    "Voyage embedding provider selected but VOYAGE_API_KEY not set — falling back to OpenAI embeddings"
                )
                self._provider = "openai"
                self._model = "text-embedding-3-small"

        if self._provider == "openai":
            self._openai = AsyncOpenAI(api_key=config.openai_api_key)

    async def embed(self, text: str) -> list[float]:
        """Generate an embedding for a single text."""
        if self._provider == "voyage":
            return (await self._voyage_embed([text]))[0]
        return await self._openai_embed(text)

    async def embed_batch(self, texts: list[str]) -> list[list[float]]:
        """Generate embeddings for multiple texts."""
        if not texts:
            return []
        if self._provider == "voyage":
            return await self._voyage_embed(texts)
        return await self._openai_embed_batch(texts)

    async def _openai_embed(self, text: str) -> list[float]:
        response = await self._openai.embeddings.create(
            input=text,
            model=self._model,
            dimensions=self._dimensions,
        )
        return response.data[0].embedding

    async def _openai_embed_batch(self, texts: list[str]) -> list[list[float]]:
        response = await self._openai.embeddings.create(
            input=texts,
            model=self._model,
            dimensions=self._dimensions,
        )
        return [item.embedding for item in response.data]

    async def _voyage_embed(self, texts: list[str]) -> list[list[float]]:
        payload = {
            "input": texts,
            "model": self._model,
            "output_dimension": self._dimensions,
        }
        async with httpx.AsyncClient() as client:
            resp = await client.post(
                VOYAGE_API_URL,
                json=payload,
                headers={
                    "Authorization": f"Bearer {self.config.voyage_api_key}",
                    "Content-Type": "application/json",
                },
                timeout=30.0,
            )
            resp.raise_for_status()
            data = resp.json()
        return [item["embedding"] for item in data["data"]]
