"""Embedding generation for semantic search via pgvector.

Priority:
  1. LiteLLM proxy — model from Redis settings (overrides env)
  2. LiteLLM proxy — model from LITELLM_EMBEDDING_MODEL env
  3. AWS Bedrock Titan Embed V2 (direct fallback)
"""
import logging

from app.config import settings

logger = logging.getLogger(__name__)


def _get_embedding_model() -> str:
    """Return the active embedding model: Redis setting takes precedence over env."""
    try:
        import redis as redis_lib
        r = redis_lib.from_url(settings.REDIS_URL, decode_responses=True)
        model = r.get("settings:embedding_model")
        if model:
            return model
    except Exception:
        pass
    return settings.LITELLM_EMBEDDING_MODEL


def _text_for_question(question_text: str, options: list[str] | None) -> str:
    """Build the text to embed for a question — stem + options, no explanation."""
    parts = [question_text]
    if options:
        parts.extend(options)
    return " ".join(parts)[:4000]


def generate_embedding(text: str) -> list[float] | None:
    """Generate a 1024-dim embedding.

    Priority:
      1. LiteLLM proxy (openai/titan-embed-v2) — scores ~0.71 cosine similarity
      2. AWS Bedrock direct — fallback, scores ~0.48
    """
    clean = " ".join(text.split())[:4000]
    if not clean:
        return None

    # ── 1. LiteLLM proxy (direct httpx — avoids LiteLLM param validation) ──
    embedding_model = _get_embedding_model()
    api_base = (settings.LITELLM_API_BASE or "").rstrip("/").removesuffix("/v1")
    if embedding_model and settings.LITELLM_API_KEY and api_base:
        try:
            import httpx, json as _json
            body: dict = {"model": embedding_model, "input": [clean], "dimensions": settings.EMBEDDING_DIMENSIONS}
            resp = httpx.post(
                f"{api_base}/v1/embeddings",
                headers={"Authorization": f"Bearer {settings.LITELLM_API_KEY}", "Content-Type": "application/json"},
                content=_json.dumps(body),
                timeout=30,
            )
            resp.raise_for_status()
            emb = resp.json()["data"][0]["embedding"]
            if len(emb) == settings.EMBEDDING_DIMENSIONS:
                return emb
            logger.warning(f"Embedding dim mismatch: got {len(emb)}, expected {settings.EMBEDDING_DIMENSIONS}")
        except Exception as e:
            logger.warning(f"LiteLLM embedding failed: {e}")

    # ── 2. AWS Bedrock Titan direct (fallback) ──────────────────
    if settings.AWS_ACCESS_KEY_ID and settings.AWS_SECRET_ACCESS_KEY:
        try:
            import boto3, json
            client = boto3.client(
                "bedrock-runtime",
                aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
                aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
                region_name=settings.AWS_BEDROCK_REGION or "us-east-1",
            )
            body = json.dumps({
                "inputText": clean,
                "dimensions": settings.EMBEDDING_DIMENSIONS,
                "normalize": True,
            })
            resp = client.invoke_model(
                modelId="amazon.titan-embed-text-v2:0",
                body=body,
                contentType="application/json",
                accept="application/json",
            )
            return json.loads(resp["body"].read())["embedding"]
        except Exception as e:
            logger.warning(f"Bedrock embedding failed: {e}")

    return None


def embed_question(question) -> bool:
    """Generate and store embedding for a Question ORM object. Returns True on success."""
    text = _text_for_question(question.question_text, question.options)
    emb = generate_embedding(text)
    if emb:
        question.embedding = emb
        return True
    return False
