#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Dark Pocket — Übersetzung aller Sprach-Dateien via lokales LibreTranslate

Voraussetzung: LibreTranslate läuft lokal (z.B. via Docker):
    docker run -ti --rm -p 5000:5000 libretranslate/libretranslate

Oder installiert via pip:
    pip install libretranslate && libretranslate --port 5000
"""

import argparse
import os
import re
import sys
import time
import json
from pathlib import Path

import requests

# ── Farben / Logging ──────────────────────────────────────────────────────────
def write_ok(msg):   print(f"  ✓ {msg}")
def write_warn(msg): print(f"  ⚠ {msg}")
def write_err(msg):  print(f"  ✗ {msg}")
def write_head(msg): print(f"\n═══ {msg} ═══")

# ── Sprachkarte: ISO-Code → LibreTranslate-Code ───────────────────────────────
LT_MAP = {
    "be": "be", "ber": "ber", "bn": "bn", "zh": "zh",
    "sr": "sr", "mk": "mk", "uk": "uk", "bg": "bg",
    "hr": "hr", "sl": "sl", "sk": "sk", "cs": "cs",
    "hu": "hu", "ro": "ro", "pl": "pl", "ru": "ru",
    "tr": "tr", "ar": "ar", "fa": "fa", "ur": "ur",
    "hi": "hi", "ta": "ta", "ja": "ja", "ko": "ko",
    "vi": "vi", "th": "th", "id": "id", "ms": "ms",
    "sw": "sw", "ha": "ha", "am": "am", "yo": "yo",
    "ig": "ig", "af": "af", "sn": "sn", "ny": "ny",
    "zu": "zu", "xh": "xh", "st": "st", "lg": "lg",
    "ln": "ln", "rw": "rw", "wo": "wo", "om": "om",
    "ti": "ti", "mg": "mg", "so": "so",
    "de": "de", "en": "en", "fr": "fr", "es": "es",
    "it": "it", "nl": "nl", "pt": "pt", "sv": "sv",
    "no": "no", "da": "da", "fi": "fi", "is": "is",
    "et": "et", "lv": "lv", "lt": "lt",
}

# Sprachen, die LibreTranslate NICHT unterstützt → überspringen
LT_UNSUPPORTED = {
    "ber", "ha", "am", "yo", "ig", "sn", "ny", "st", "lg",
    "ln", "rw", "wo", "om", "ti", "mg", "so", "is", "et",
    "lv", "lt"
}

# ── Übersetzungsfunktion ──────────────────────────────────────────────────────
def translate_text(text, target_lang, source_lang, api_url):
    if not text or text.strip() == "":
        return text

    # Platzhalter schützen: {name}, {n} → temporär ersetzen
    placeholders = {}
    protected = text
    ph_pattern = r"\{[a-zA-Z0-9_]+\}"
    ph_idx = 0

    for m in re.finditer(ph_pattern, text):
        token = f"XXPH{ph_idx}XX"
        placeholders[token] = m.group(0)
        protected = protected.replace(m.group(0), token)
        ph_idx += 1

    try:
        body = {
            "q": protected,
            "source": source_lang,
            "target": target_lang,
            "format": "text",
        }
        resp = requests.post(
            f"{api_url}/translate",
            data=json.dumps(body),
            headers={"Content-Type": "application/json; charset=utf-8"},
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()
        translated = data.get("translatedText", protected)

        # Platzhalter wiederherstellen
        for token, original in placeholders.items():
            translated = translated.replace(token, original)

        return translated
    except Exception:
        # Fallback: Originaltext
        return text

# ── PHP-Basisdatei parsen ─────────────────────────────────────────────────────
def parse_php_lang_file(path):
    content = Path(path).read_text(encoding="utf-8")
    keys = {}

    # Regex: 'key'=>'value'
    pattern = r"'\s*([a-zA-Z0-9_]+)\s*'\s*=>\s*'((?:[^'\\]|\\.)*)'"
    for m in re.finditer(pattern, content):
        key = m.group(1)
        val = m.group(2)
        # unescape \' → '
        val = val.replace("\\'", "'")
        keys[key] = val

    return keys

# ── PHP-Datei schreiben ───────────────────────────────────────────────────────
def write_php_lang_file(path, translations):
    lines = ["<?php return ["]
    for key in sorted(translations.keys()):
        val = translations[key] if translations[key] is not None else ""
        # escapen
        val = val.replace("\\", "\\\\").replace("'", "\\'")
        lines.append(f"  '{key}'=>'{val}',")
    lines.append("];")
    Path(path).write_text("\n".join(lines), encoding="utf-8")

# ── Hauptfunktion ─────────────────────────────────────────────────────────────
def main():
    parser = argparse.ArgumentParser(
        description="Dark Pocket — Übersetzung aller Sprach-Dateien via lokales LibreTranslate"
    )
    parser.add_argument("--LangDir", default=r".\app\includes\lang")
    parser.add_argument("--BaseFile", default=r".\app\includes\lang\de.php")
    parser.add_argument("--ApiUrl", default="http://localhost:5000")
    parser.add_argument("--SourceLang", default="de")
    parser.add_argument(
        "--OnlyLangs",
        nargs="*",
        default=[],
        help="Nur diese Sprachcodes übersetzen (z.B. en fr tr)",
    )
    parser.add_argument(
        "--DryRun",
        action="store_true",
        help="Nur ausgeben, keine Dateien schreiben",
    )
    parser.add_argument(
        "--SkipExisting",
        action="store_true",
        help="Bereits vorhandene Dateien überspringen",
    )
    parser.add_argument(
        "--DelayMs",
        type=int,
        default=200,
        help="Pause zwischen Requests in Millisekunden",
    )

    args = parser.parse_args()

    lang_dir = Path(args.LangDir)
    base_file = Path(args.BaseFile)
    api_url = args.ApiUrl.rstrip("/")
    source_lang = args.SourceLang
    only_langs = set(args.OnlyLangs or [])
    dry_run = args.DryRun
    skip_existing = args.SkipExisting
    delay_ms = args.DelayMs

    # ── Zielsprachen bestimmen ────────────────────────────────────────────────
    all_langs = []
    for f in lang_dir.glob("*.php"):
        base_name = f.stem
        if base_name == "de" or base_name == source_lang:
            continue
        all_langs.append(base_name)

    if only_langs:
        all_langs = [l for l in all_langs if l in only_langs]

    write_head("Dark Pocket LibreTranslate")
    print(f"  API:    {api_url}")
    print(f"  Basis:  {base_file}  (→ {source_lang})")
    print(f"  Ziele:  {len(all_langs)} Sprachen")
    if dry_run:
        write_warn("DRY RUN — keine Dateien werden geschrieben")

    # ── Verbindungstest ───────────────────────────────────────────────────────
    write_head("Verbindungstest")
    try:
        resp = requests.get(f"{api_url}/languages", timeout=10)
        resp.raise_for_status()
        languages = resp.json()
        supported_codes = {l["code"] for l in languages}
        write_ok(f"LibreTranslate erreichbar — {len(supported_codes)} Sprachen verfügbar")
    except Exception:
        write_err(f"LibreTranslate nicht erreichbar unter {api_url}")
        write_err("Bitte starten: docker run -ti --rm -p 5000:5000 libretranslate/libretranslate")
        sys.exit(1)

    # ── Basis-Datei einlesen ─────────────────────────────────────────────────
    write_head("Basis-Datei einlesen")
    if not base_file.exists():
        write_err(f"Basis-Datei nicht gefunden: {base_file}")
        sys.exit(1)

    keys = parse_php_lang_file(base_file)
    write_ok(f"{len(keys)} Schlüssel gefunden")

    # ── Übersetzung starten ───────────────────────────────────────────────────
    write_head("Übersetzung starten")
    total = len(all_langs)
    done = 0
    skipped = 0
    failed = 0

    for lang in all_langs:
        done += 1
        out_file = lang_dir / f"{lang}.php"
        lt_code = LT_MAP.get(lang, lang)

        # Nicht-unterstützte Sprachen überspringen
        if lang in LT_UNSUPPORTED:
            write_warn(f"[{done}/{total}] {lang} ({lt_code}) — nicht in LibreTranslate, übersprungen")
            skipped += 1
            continue

        # LibreTranslate Verfügbarkeit prüfen
        if lt_code not in supported_codes:
            write_warn(f"[{done}/{total}] {lang} ({lt_code}) — nicht verfügbar in dieser LibreTranslate-Instanz")
            skipped += 1
            continue

        print(f"  [{done}/{total}] {lang} ", end="")

        # Datei ggf. überspringen
        if skip_existing and out_file.exists():
            write_warn("bereits vorhanden, übersprungen (--SkipExisting)")
            skipped += 1
            continue

        translated = {}
        fail_count = 0

        for k, v in keys.items():
            tval = translate_text(v, lt_code, source_lang, api_url)
            translated[k] = tval
            if tval == v and len(v) > 3:
                fail_count += 1
            if delay_ms > 0:
                time.sleep(delay_ms / 1000.0)

        if fail_count > (len(keys) * 0.5):
            write_warn(f"Viele unveränderte Werte ({fail_count}) — möglicherweise Fehler")
            failed += 1
        else:
            write_ok(f"({len(keys)} Strings)")

        if not dry_run:
            write_php_lang_file(out_file, translated)

    # ── Zusammenfassung ───────────────────────────────────────────────────────
    write_head("Fertig")
    write_ok(f"Übersetzt: {done - skipped - failed}")
    if skipped > 0:
        write_warn(f"Übersprungen: {skipped}")
    if failed > 0:
        write_warn(f"Fehler:       {failed}")

    print("")
    print("  Verwendung:")
    print("    # Alle Sprachen übersetzen:")
    print("    python darkpocket_translate.py")
    print("")
    print("    # Nur bestimmte Sprachen:")
    print("    python darkpocket_translate.py --OnlyLangs en fr tr")
    print("")
    print("    # Trockentest (nichts schreiben):")
    print("    python darkpocket_translate.py --DryRun")
    print("")
    print("    # Vorhandene überspringen (nur neue/fehlende):")
    print("    python darkpocket_translate.py --SkipExisting")
    print("")
    print("    # Andere LibreTranslate-Instanz:")
    print("    python darkpocket_translate.py --ApiUrl http://192.168.1.100:5000")


if __name__ == "__main__":
    main()
