import logging

from openai import AsyncOpenAI, OpenAI

from config import OPENAI_API_KEY

logger = logging.getLogger(__name__)

__all__ = [
    "create_embedding",
    "create_embedding_async",
    "create_embeddings_async",
    "get_async_embedding_client",
    "get_embedding_client",
]


class EmbeddingClientManager:
    """
    Singleton Class quản lý OpenAI Embedding Client (Sync & Async).
    """

    def __init__(self):
        self._client: OpenAI | None = None
        self._async_client: AsyncOpenAI | None = None

    def get_client(self) -> OpenAI:
        """Sync Client lazy loading"""
        if self._client is None:
            if not OPENAI_API_KEY:
                raise RuntimeError("CRITICAL: OPENAI_API_KEY chưa được thiết lập")
            self._client = OpenAI(api_key=OPENAI_API_KEY)
        return self._client

    def get_async_client(self) -> AsyncOpenAI:
        """Async Client lazy loading"""
        if self._async_client is None:
            if not OPENAI_API_KEY:
                raise RuntimeError("CRITICAL: OPENAI_API_KEY chưa được thiết lập")
            self._async_client = AsyncOpenAI(api_key=OPENAI_API_KEY)
        return self._async_client


logger = logging.getLogger(__name__)

# NOTE:
# - TẠM THỜI KHÔNG DÙNG REDIS CACHE CHO EMBEDDING để tránh phụ thuộc Redis/aioredis.
# - Nếu cần bật lại cache, import `redis_cache` từ `common.cache`
#   và dùng như các đoạn code cũ (get_embedding / set_embedding).

# --- Singleton ---
_manager = EmbeddingClientManager()
get_embedding_client = _manager.get_client
get_async_embedding_client = _manager.get_async_client


def create_embedding(text: str) -> list[float]:
    """Sync embedding generation (No cache for sync to avoid overhead)"""
    try:
        client = get_embedding_client()
        response = client.embeddings.create(model="text-embedding-3-small", input=text)
        return response.data[0].embedding
    except Exception as e:
        logger.error(f"Error creating embedding (sync): {e}")
        return []


async def create_embedding_async(text: str) -> list[float]:
    """
    Async embedding generation (KHÔNG dùng cache).
    Nếu sau này cần cache lại, có thể thêm redis_cache.get_embedding / set_embedding.
    """
    try:
        client = get_async_embedding_client()
        response = await client.embeddings.create(model="text-embedding-3-small", input=text)
        embedding = response.data[0].embedding
        return embedding
    except Exception as e:
        logger.error(f"Error creating embedding (async): {e}")
        return []


async def create_embeddings_async(texts: list[str]) -> list[list[float]]:
    """
    Batch async embedding generation with per-item Layer 2 Cache.
    """
    try:
        if not texts:
            return []

        client = get_async_embedding_client()
        response = await client.embeddings.create(model="text-embedding-3-small", input=texts)

        # Giữ nguyên thứ tự embedding theo order input
        sorted_data = sorted(response.data, key=lambda x: x.index)
        results = [item.embedding for item in sorted_data]

        return results
    except Exception as e:
        logger.error(f"Error creating batch embeddings (async): {e}")
        return [[] for _ in texts]
