"""RBS REGAL — Item Name Multi-Language Translation.

Translates the `name` field of items into the 13 supported languages, stored
in items.name_translations as { lang_code: translated_name }.

Endpoints (mounted under /api/items-i18n):
    POST /{item_id}/translate           — translate one item's name to all 13 languages
    POST /bulk-translate                — bulk translate up to 200 items at once
    GET  /{item_id}/name?lang=xx        — fetch the localized name (with fallback)
"""
from __future__ import annotations

from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel, Field

from auth import get_current_user
from bson import ObjectId
from translation_engine import (
    SUPPORTED_CODES,
    _llm_translate_batch,
    _cache_get_many,
    _cache_set_many,
)

router = APIRouter(prefix="/api/items-i18n", tags=["items-i18n"])


def _now_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


# Languages we translate into by default (everything except English source)
DEFAULT_TARGETS = [c for c in SUPPORTED_CODES if c != "en"]


async def _translate_one_name(db, name: str) -> dict[str, str]:
    """Translate a single product name into all supported languages."""
    out: dict[str, str] = {"en": name}
    for lang in DEFAULT_TARGETS:
        # cache check
        cached = await _cache_get_many(db, lang, [name])
        if name in cached:
            out[lang] = cached[name]
            continue
        # LLM call
        tr = await _llm_translate_batch([name], lang)
        translated = tr.get(name, name)
        out[lang] = translated
        await _cache_set_many(db, lang, {name: translated})
    return out


class TranslateOneIn(BaseModel):
    target_langs: list[str] | None = None  # default = all supported except en


@router.post("/{item_id}/translate")
async def translate_one(item_id: str, payload: TranslateOneIn, request: Request, user=Depends(get_current_user)):
    db = request.app.state.db
    try:
        oid = ObjectId(item_id)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid item id")
    item = await db.items.find_one({"_id": oid})
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    name = item.get("name") or ""
    if not name.strip():
        raise HTTPException(status_code=400, detail="Item has empty name")

    targets = payload.target_langs or DEFAULT_TARGETS
    targets = [t for t in targets if t in SUPPORTED_CODES and t != "en"]

    translations: dict[str, str] = {"en": name}
    for lang in targets:
        cached = await _cache_get_many(db, lang, [name])
        if name in cached:
            translations[lang] = cached[name]
            continue
        tr = await _llm_translate_batch([name], lang)
        translations[lang] = tr.get(name, name)
        await _cache_set_many(db, lang, {name: translations[lang]})

    await db.items.update_one(
        {"_id": oid},
        {"$set": {
            "name_translations": translations,
            "name_translations_updated_at": _now_iso(),
            "name_translations_updated_by": user.get("email", ""),
        }},
    )
    return {"item_id": item_id, "name_translations": translations, "count": len(translations)}


class BulkTranslateIn(BaseModel):
    company_id: str
    item_ids: list[str] = Field(default_factory=list)  # empty = ALL items in the company
    target_langs: list[str] | None = None
    max_items: int = 200


@router.post("/bulk-translate")
async def bulk_translate(payload: BulkTranslateIn, request: Request, user=Depends(get_current_user)):
    db = request.app.state.db

    # Build target list
    targets = payload.target_langs or DEFAULT_TARGETS
    targets = [t for t in targets if t in SUPPORTED_CODES and t != "en"]
    if not targets:
        raise HTTPException(status_code=400, detail="No valid target languages")

    # Resolve item list
    if payload.item_ids:
        try:
            oids = [ObjectId(i) for i in payload.item_ids]
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid item id in list")
        cur = db.items.find({"company_id": payload.company_id, "_id": {"$in": oids}})
    else:
        cur = db.items.find({"company_id": payload.company_id}).limit(int(payload.max_items))
    items = await cur.to_list(length=int(payload.max_items))

    if not items:
        return {"translated": 0, "languages": targets, "message": "No items found"}

    # Build per-language batches (one LLM call per language for ALL names)
    names = [it.get("name", "") for it in items if it.get("name")]
    unique_names = list(dict.fromkeys(names))  # preserve order, dedupe

    translation_map: dict[str, dict[str, str]] = {lang_code: {} for lang_code in targets}
    for lang in targets:
        cached = await _cache_get_many(db, lang, unique_names)
        translation_map[lang].update(cached)
        missing = [n for n in unique_names if n not in cached]
        if missing:
            # Batch in chunks of 40
            for i in range(0, len(missing), 40):
                batch = missing[i:i + 40]
                fresh = await _llm_translate_batch(batch, lang)
                translation_map[lang].update(fresh)
                await _cache_set_many(db, lang, fresh)

    # Write per-item name_translations
    now = _now_iso()
    user_email = user.get("email", "")
    write_ops = 0
    from pymongo import UpdateOne
    bulk = []
    for it in items:
        name = it.get("name", "")
        if not name:
            continue
        existing = it.get("name_translations") or {}
        new_trans = dict(existing)
        new_trans["en"] = name
        for lang in targets:
            new_trans[lang] = translation_map[lang].get(name, name)
        bulk.append(UpdateOne(
            {"_id": it["_id"]},
            {"$set": {
                "name_translations": new_trans,
                "name_translations_updated_at": now,
                "name_translations_updated_by": user_email,
            }},
        ))
        write_ops += 1
    if bulk:
        await db.items.bulk_write(bulk, ordered=False)

    return {
        "translated": write_ops,
        "languages": targets,
        "unique_names": len(unique_names),
    }


@router.get("/{item_id}/name")
async def get_localized_name(item_id: str, request: Request, lang: str = "en", user=Depends(get_current_user)):
    """Return the localized item name with smart fallback (lang → en → raw name)."""
    db = request.app.state.db
    try:
        oid = ObjectId(item_id)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid item id")
    it = await db.items.find_one({"_id": oid}, {"name": 1, "name_translations": 1})
    if not it:
        raise HTTPException(status_code=404, detail="Item not found")
    nt = it.get("name_translations") or {}
    raw = it.get("name", "")
    name = nt.get(lang) or nt.get("en") or raw
    return {"item_id": item_id, "lang": lang, "name": name, "raw": raw, "has_translation": bool(nt.get(lang))}
