"""
Singleton embedding model for the Orchestrator.

Loads all-MiniLM-L6-v2 once at module level (lazy singleton pattern).
The model produces 384-dimensional embeddings compatible with the
conversation_embeddings.embedding vector(384) column.

Why a singleton: sentence-transformers models are ~100MB and take ~2s to load.
Loading per-request would be catastrophically slow. Loading at module level
means the model is loaded once when the Celery worker starts.

Thread safety: SentenceTransformer.encode() releases the GIL and is safe to
call from multiple Celery threads simultaneously.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from sentence_transformers import SentenceTransformer

logger = logging.getLogger(__name__)

# Embedding model name — must match the vector(384) column dimension
_MODEL_NAME = "all-MiniLM-L6-v2"

# Lazy singleton — loaded on first use, not at import time
# This avoids 2s+ load time when the module is imported but not used
_model: "SentenceTransformer | None" = None


def get_embedding_model() -> "SentenceTransformer":
    """
    Return the singleton SentenceTransformer model, loading it on first call.

    Thread-safe: multiple Celery workers can call this concurrently.
    The model is loaded only once per process.

    Returns:
        Loaded SentenceTransformer model (all-MiniLM-L6-v2, 384 dims).
    """
    global _model
    if _model is None:
        logger.info("Loading embedding model %s (first use)", _MODEL_NAME)
        from sentence_transformers import SentenceTransformer

        _model = SentenceTransformer(_MODEL_NAME)
        logger.info("Embedding model %s loaded", _MODEL_NAME)
    return _model


def embed_text(text: str) -> list[float]:
    """
    Embed a single text string using all-MiniLM-L6-v2.

    Args:
        text: The text to embed.

    Returns:
        384-dimensional float list.
    """
    model = get_embedding_model()
    embedding = model.encode(text, normalize_embeddings=True)
    return embedding.tolist()


def embed_texts(texts: list[str]) -> list[list[float]]:
    """
    Embed a list of text strings in batch (more efficient than one-by-one).

    Args:
        texts: List of strings to embed.

    Returns:
        List of 384-dimensional float lists, same order as input.
    """
    model = get_embedding_model()
    embeddings = model.encode(texts, normalize_embeddings=True, batch_size=32)
    return [e.tolist() for e in embeddings]
