"""Build embeddings for catalog descriptions using OpenRouter text-embedding-3-small."""

import json
import os
import time
from pathlib import Path

import numpy as np
import requests

EMBEDDING_MODEL = "openai/text-embedding-3-small"
BATCH_SIZE = 50
ENV_PATH = "/home/videobot/dev/.env"


def _load_api_key():
    key = os.environ.get("OPENROUTER_API_KEY")
    if key:
        return key
    with open(ENV_PATH, "r") as f:
        for line in f:
            if line.startswith("OPENROUTER_API_KEY="):
                return line.strip().split("=", 1)[1]
    raise RuntimeError("OPENROUTER_API_KEY not found")


def _build_text(entry: dict, text_fields: list = None) -> str:
    """Combine metadata fields into embedding text."""
    if text_fields is None:
        text_fields = ["title", "description", "year", "materials",
                       "index_commentary", "tags"]
    parts = []
    for field in text_fields:
        val = entry.get(field)
        if val:
            if field in ("title", "description"):
                parts.append(str(val))
            else:
                parts.append(f"{field.replace('_', ' ').title()}: {val}")
    return "\n".join(parts)


def _embed_batch(api_key: str, texts: list) -> list:
    """Embed a batch of texts via OpenRouter with retries."""
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    }
    truncated = [t[:4000] for t in texts]
    payload = {
        "model": EMBEDDING_MODEL,
        "input": truncated,
    }

    for attempt in range(3):
        try:
            resp = requests.post(
                "https://openrouter.ai/api/v1/embeddings",
                headers=headers,
                json=payload,
                timeout=120,
            )
            if resp.status_code == 429:
                time.sleep(2 ** (attempt + 1))
                continue
            if resp.status_code != 200:
                raise RuntimeError(
                    f"Embedding API error {resp.status_code}: {resp.text[:300]}")
            data = resp.json()
            embeddings = [item["embedding"]
                          for item in sorted(data["data"], key=lambda x: x["index"])]
            return embeddings
        except requests.exceptions.Timeout:
            if attempt < 2:
                print(f" timeout, retrying...", end="", flush=True)
                time.sleep(3)
            else:
                raise
    raise RuntimeError("embed_batch failed after 3 attempts")


def build_embeddings(catalog_path: str, output_dir: str,
                     text_fields: list = None, api_key: str = None):
    """Build embeddings from catalog descriptions.

    Args:
        catalog_path: Path to catalog.json
        output_dir: Directory to write embeddings.npz + embeddings_index.json
        text_fields: Fields to combine for embedding text.
                     Default: ["title", "description", "year", "materials",
                               "index_commentary", "tags"]
        api_key: OpenRouter API key (auto-loaded if None)
    """
    if api_key is None:
        api_key = _load_api_key()

    with open(catalog_path, "r", encoding="utf-8") as f:
        catalog = json.load(f)

    # Filter to items with descriptions
    items = [(i, e) for i, e in enumerate(catalog)
             if e.get("description") and not e.get("skip")]
    print(f"Catalog: {len(catalog)} total, {len(items)} with descriptions to embed")

    if not items:
        print("No items to embed. Run describe_images first.")
        return

    texts = [_build_text(e, text_fields) for _, e in items]
    ids = [e["id"] for _, e in items]

    all_embeddings = []
    for batch_start in range(0, len(texts), BATCH_SIZE):
        batch_end = min(batch_start + BATCH_SIZE, len(texts))
        batch = texts[batch_start:batch_end]
        print(f"  Embedding batch {batch_start+1}-{batch_end}/{len(texts)}...",
              end="", flush=True)
        embeddings = _embed_batch(api_key, batch)
        all_embeddings.extend(embeddings)
        print(f" OK ({len(embeddings[0])} dims)")

    embeddings_array = np.array(all_embeddings, dtype=np.float32)
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    npz_path = output_dir / "embeddings.npz"
    np.savez_compressed(npz_path, embeddings=embeddings_array)

    index = [{"idx": i, "id": ids[i], "catalog_idx": items[i][0]}
             for i in range(len(ids))]
    index_path = output_dir / "embeddings_index.json"
    with open(index_path, "w", encoding="utf-8") as f:
        json.dump(index, f, ensure_ascii=False, indent=2)

    print(f"\nSaved {len(all_embeddings)} embeddings ({embeddings_array.shape}) "
          f"to {npz_path}")
    print(f"Index saved to {index_path}")
