#!/usr/bin/env python3
"""Private, local-only translation service for the FilyX interface.

It listens exclusively on 127.0.0.1.  The FilyX web app is its sole client;
there is no public endpoint, account, API key, telemetry, or remote request.
"""
from __future__ import annotations

import json
import threading
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

import argostranslate.translate

LANGUAGE_CODES = {"en": "en", "es": "es", "ar": "ar", "pt": "pt", "de": "de"}
TRANSLATION_LOCK = threading.Lock()


def translator(target: str):
    languages = {language.code: language for language in argostranslate.translate.get_installed_languages()}
    source = languages.get("fr")
    destination = languages.get(LANGUAGE_CODES.get(target, ""))
    if source is None or destination is None:
        raise ValueError("language model unavailable")
    english = languages.get("en")
    if target == "en":
        return source.get_translation(destination)
    if english is None:
        raise ValueError("English pivot unavailable")
    return (source.get_translation(english), english.get_translation(destination))


class Handler(BaseHTTPRequestHandler):
    server_version = "FilyXLocalTranslate/1.0"

    def log_message(self, _format: str, *_args: object) -> None:
        # Never log source texts: they are UI labels, but keeping this service
        # silent also guarantees streamer content cannot leak into journald.
        return

    def send_json(self, status: int, payload: dict) -> None:
        body = json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.send_header("Cache-Control", "no-store")
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self) -> None:
        if self.path != "/health":
            self.send_json(HTTPStatus.NOT_FOUND, {"ok": False})
            return
        installed = {language.code for language in argostranslate.translate.get_installed_languages()}
        self.send_json(HTTPStatus.OK, {"ok": True, "languages": sorted(installed)})

    def do_POST(self) -> None:
        if self.path != "/translate":
            self.send_json(HTTPStatus.NOT_FOUND, {"ok": False})
            return
        try:
            length = int(self.headers.get("Content-Length", "0"))
            if length < 2 or length > 100_000:
                raise ValueError("invalid request length")
            payload = json.loads(self.rfile.read(length).decode("utf-8"))
            target = str(payload.get("target", ""))
            texts = payload.get("texts", [])
            if target not in LANGUAGE_CODES or not isinstance(texts, list) or not texts or len(texts) > 60:
                raise ValueError("invalid request")
            values = [str(value).strip() for value in texts]
            if any(not value or len(value) > 1800 for value in values) or sum(map(len, values)) > 60_000:
                raise ValueError("invalid text")
            with TRANSLATION_LOCK:
                engine = translator(target)
                if isinstance(engine, tuple):
                    translations = [engine[1].translate(engine[0].translate(value)) for value in values]
                else:
                    translations = [engine.translate(value) for value in values]
            self.send_json(HTTPStatus.OK, {"ok": True, "translations": translations})
        except Exception as error:
            self.send_json(HTTPStatus.UNPROCESSABLE_ENTITY, {"ok": False, "error": "translation unavailable", "detail": str(error)[:180]})


if __name__ == "__main__":
    ThreadingHTTPServer(("127.0.0.1", 5011), Handler).serve_forever()
