"""Translation (EN<->AR, either direction) with a fallback chain so captions
never silently die mid-presentation.

Order:
  1. Official Google Cloud Translate (best reliability) - used automatically if
     a service-account .json is found in the app folder or via the standard
     GOOGLE_APPLICATION_CREDENTIALS environment variable. First 500K
     characters/month are free on Google's permanent free tier.
  2. Official Azure Translator - used if "azure_translator_key" is set in
     settings.json (free F0 tier: 2M characters/month). Set
     "azure_translator_region" too unless the resource is global.
  3. Free Google web endpoint via deep-translator (no key needed).
Returns None if everything fails; the UI then keeps the previous caption and
shows a status warning instead of going blank.
"""

import glob
import html
import os
import threading

from config import APP_DIR, load as _load_settings

_lock = threading.Lock()
_cloud_client = None
_cloud_tried = False
_free_translators = {}  # (source, target) -> GoogleTranslator

#: set by translate() so the UI can display which engine is live
last_engine = "none"


def _get_cloud_client():
    """Lazily build the official Google client if credentials exist."""
    global _cloud_client, _cloud_tried
    if _cloud_tried:
        return _cloud_client
    _cloud_tried = True

    if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"):
        # Convenience: any service-account json dropped into the app folder works.
        for path in glob.glob(os.path.join(APP_DIR, "*.json")):
            base = os.path.basename(path)
            if base == "settings.json":
                continue
            try:
                import json
                with open(path, "r", encoding="utf-8") as f:
                    if json.load(f).get("type") == "service_account":
                        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = path
                        break
            except (OSError, ValueError):
                continue

    if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"):
        return None

    try:
        from google.cloud import translate_v2
        _cloud_client = translate_v2.Client()
    except Exception:
        _cloud_client = None
    return _cloud_client


def _get_free_translator(source, target):
    key = (source, target)
    if key not in _free_translators:
        from deep_translator import GoogleTranslator
        _free_translators[key] = GoogleTranslator(source=source, target=target)
    return _free_translators[key]


_azure_cfg = None  # (key, region) or ("", "") once loaded


def _get_azure_cfg():
    global _azure_cfg
    if _azure_cfg is None:
        s = _load_settings()
        _azure_cfg = (str(s.get("azure_translator_key") or "").strip(),
                      str(s.get("azure_translator_region") or "").strip())
    return _azure_cfg


def _azure_translate(text, source, target):
    """Official Azure Translator REST call. Raises on any failure so the
    chain falls through. Short timeout: leave room for the free fallback
    inside the pipeline's 5-second translation budget."""
    key, region = _get_azure_cfg()
    import requests
    headers = {"Ocp-Apim-Subscription-Key": key,
               "Content-Type": "application/json"}
    if region:
        headers["Ocp-Apim-Subscription-Region"] = region
    r = requests.post(
        "https://api.cognitive.microsofttranslator.com/translate",
        params={"api-version": "3.0", "from": source, "to": target},
        headers=headers, json=[{"text": text}], timeout=2.5)
    r.raise_for_status()
    return r.json()[0]["translations"][0]["text"]


def translate(text, source="en", target="ar"):
    """Translate text between languages. Thread-safe. Returns str or None."""
    global last_engine
    text = (text or "").strip()
    if not text:
        return ""

    with _lock:
        client = _get_cloud_client()
        if client is not None:
            try:
                out = client.translate(text, target_language=target,
                                       source_language=source)["translatedText"]
                last_engine = "google-cloud"
                return html.unescape(out)
            except Exception:
                pass  # fall through

        if _get_azure_cfg()[0]:
            try:
                out = _azure_translate(text, source, target)
                if out:
                    last_engine = "azure"
                    return out
            except Exception:
                pass  # fall through to free endpoint

        try:
            out = _get_free_translator(source, target).translate(text)
            last_engine = "google-free"
            if out:
                return html.unescape(out)
        except Exception:
            pass

    last_engine = "offline"
    return None
