"""
TranslationService — Real-time Lyric Translation for Subify v3.0 Ultra with SQLite caching
"""

import os
import ssl
import json
import sqlite3
import threading
import subprocess
from urllib.request import urlopen, Request
from urllib.parse import urlencode

CACHE_DIR = os.path.expanduser('~/.subify')
DB_PATH = os.path.join(CACHE_DIR, 'cache.db')


def _init_trans_db():
    os.makedirs(CACHE_DIR, exist_ok=True)
    with sqlite3.connect(DB_PATH) as conn:
        conn.execute('''
            CREATE TABLE IF NOT EXISTS translation_cache (
                source_text TEXT PRIMARY KEY,
                target_lang TEXT,
                translated_text TEXT
            )
        ''')
        conn.commit()


def _get_cached_translation(text: str, target_lang: str) -> str:
    try:
        if os.path.exists(DB_PATH):
            with sqlite3.connect(DB_PATH) as conn:
                cursor = conn.cursor()
                cursor.execute(
                    'SELECT translated_text FROM translation_cache WHERE source_text = ? AND target_lang = ?',
                    (text, target_lang)
                )
                row = cursor.fetchone()
                if row and row[0]:
                    return row[0]
    except Exception:
        pass
    return ""


def _save_cached_translation(text: str, target_lang: str, translated: str):
    try:
        _init_trans_db()
        with sqlite3.connect(DB_PATH) as conn:
            conn.execute(
                'INSERT OR REPLACE INTO translation_cache (source_text, target_lang, translated_text) VALUES (?, ?, ?)',
                (text, target_lang, translated)
            )
            conn.commit()
    except Exception:
        pass


def _create_ssl_context():
    try:
        ctx = ssl.create_default_context()
        if ctx.get_ca_certs():
            return ctx
    except Exception:
        pass
    return ssl._create_unverified_context()


class TranslationService:
    """Translates lyric lines asynchronously with persistent SQLite caching."""

    _instance = None

    @classmethod
    def shared(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    def __init__(self):
        self._ssl_ctx = _create_ssl_context()
        _init_trans_db()

    def translate_text(self, text: str, target_lang: str = 'en', callback=None):
        if not text or not text.strip():
            if callback:
                callback(text, "")
            return

        def _worker():
            source = text.strip()
            cached = _get_cached_translation(source, target_lang)
            if cached:
                if callback:
                    callback(source, cached)
                return

            translated = self._fetch_translation_api(source, target_lang)
            if translated and translated != source:
                _save_cached_translation(source, target_lang, translated)
                if callback:
                    callback(source, translated)
            else:
                if callback:
                    callback(source, "")

        thread = threading.Thread(target=_worker, daemon=True)
        thread.start()

    def _fetch_translation_api(self, text: str, target_lang: str) -> str:
        params = urlencode({'client': 'gtx', 'sl': 'auto', 'tl': target_lang, 'dt': 't', 'q': text})
        url = f"https://translate.googleapis.com/translate_a/single?{params}"

        try:
            req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
            with urlopen(req, timeout=4, context=self._ssl_ctx) as resp:
                data = json.loads(resp.read().decode('utf-8'))
                if data and isinstance(data, list) and data[0]:
                    return ''.join([item[0] for item in data[0] if item and item[0]])
        except Exception:
            pass

        try:
            res = subprocess.run(
                ['curl', '-s', '-H', 'User-Agent: Mozilla/5.0', url],
                capture_output=True, text=True, timeout=4
            )
            if res.returncode == 0 and res.stdout.strip():
                data = json.loads(res.stdout)
                if data and isinstance(data, list) and data[0]:
                    return ''.join([item[0] for item in data[0] if item and item[0]])
        except Exception:
            pass

        return ""
