"""
Internationalization (i18n) support for TTSFM Web Application

This module provides multi-language support for the Flask web application,
including language detection, translation management, and template functions.
"""

import json
import os
from typing import Dict, Any, Optional
from flask import request, session, current_app


class LanguageManager:
    """Manages language detection, translation loading, and text translation."""
    
    def __init__(self, app=None, translations_dir: str = "translations"):
        """
        Initialize the LanguageManager.
        
        Args:
            app: Flask application instance
            translations_dir: Directory containing translation files
        """
        self.translations_dir = translations_dir
        self.translations: Dict[str, Dict[str, Any]] = {}
        self.supported_languages = ['en', 'zh']
        self.default_language = 'en'
        
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        """Initialize the Flask application with i18n support."""
        app.config.setdefault('LANGUAGES', self.supported_languages)
        app.config.setdefault('DEFAULT_LANGUAGE', self.default_language)
        
        # Load translations
        self.load_translations()
        
        # Register template functions
        app.jinja_env.globals['_'] = self.translate
        app.jinja_env.globals['get_locale'] = self.get_locale
        app.jinja_env.globals['get_supported_languages'] = self.get_supported_languages
        
        # Store reference to this instance
        app.language_manager = self
    
    def load_translations(self):
        """Load all translation files from the translations directory."""
        translations_path = os.path.join(
            os.path.dirname(__file__), 
            self.translations_dir
        )
        
        if not os.path.exists(translations_path):
            print(f"Warning: Translations directory not found: {translations_path}")
            return
        
        for lang_code in self.supported_languages:
            file_path = os.path.join(translations_path, f"{lang_code}.json")
            
            if os.path.exists(file_path):
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        self.translations[lang_code] = json.load(f)
                    print(f"Info: Loaded translations for language: {lang_code}")
                except Exception as e:
                    print(f"Error: Failed to load translations for {lang_code}: {e}")
            else:
                print(f"Warning: Translation file not found: {file_path}")
    
    def get_locale(self) -> str:
        """
        Get the current locale based on user preference, session, or browser settings.
        
        Returns:
            Language code (e.g., 'en', 'zh')
        """
        # 1. Check URL parameter (for language switching)
        if 'lang' in request.args:
            lang = request.args.get('lang')
            if lang in self.supported_languages:
                session['language'] = lang
                return lang
        
        # 2. Check session (user's previous choice)
        if 'language' in session:
            lang = session['language']
            if lang in self.supported_languages:
                return lang
        
        # 3. Check browser's Accept-Language header
        if request.headers.get('Accept-Language'):
            browser_langs = request.headers.get('Accept-Language').split(',')
            for browser_lang in browser_langs:
                # Extract language code (e.g., 'zh-CN' -> 'zh')
                lang_code = browser_lang.split(';')[0].split('-')[0].strip().lower()
                if lang_code in self.supported_languages:
                    session['language'] = lang_code
                    return lang_code
        
        # 4. Fall back to default language
        return self.default_language
    
    def set_locale(self, lang_code: str) -> bool:
        """
        Set the current locale.
        
        Args:
            lang_code: Language code to set
            
        Returns:
            True if successful, False if language not supported
        """
        if lang_code in self.supported_languages:
            session['language'] = lang_code
            return True
        return False
    
    def translate(self, key: str, **kwargs) -> str:
        """
        Translate a text key to the current locale.
        
        Args:
            key: Translation key in dot notation (e.g., 'nav.home')
            **kwargs: Variables for string formatting
            
        Returns:
            Translated text or the key if translation not found
        """
        locale = self.get_locale()
        
        # Get translation for current locale
        translation = self._get_nested_value(
            self.translations.get(locale, {}), 
            key
        )
        
        # Fall back to default language if not found
        if translation is None and locale != self.default_language:
            translation = self._get_nested_value(
                self.translations.get(self.default_language, {}), 
                key
            )
        
        # Fall back to key if still not found
        if translation is None:
            translation = key
        
        # Format with variables if provided
        if kwargs and isinstance(translation, str):
            try:
                translation = translation.format(**kwargs)
            except (KeyError, ValueError):
                pass  # Ignore formatting errors
        
        return translation
    
    def _get_nested_value(self, data: Dict[str, Any], key: str) -> Optional[str]:
        """
        Get a nested value from a dictionary using dot notation.
        
        Args:
            data: Dictionary to search in
            key: Dot-separated key (e.g., 'nav.home')
            
        Returns:
            Value if found, None otherwise
        """
        keys = key.split('.')
        current = data
        
        for k in keys:
            if isinstance(current, dict) and k in current:
                current = current[k]
            else:
                return None
        
        return current if isinstance(current, str) else None
    
    def get_supported_languages(self) -> Dict[str, str]:
        """
        Get a dictionary of supported languages with their display names.
        
        Returns:
            Dictionary mapping language codes to display names
        """
        return {
            'en': 'English',
            'zh': '中文'
        }
    
    def get_language_info(self, lang_code: str) -> Dict[str, str]:
        """
        Get information about a specific language.
        
        Args:
            lang_code: Language code
            
        Returns:
            Dictionary with language information
        """
        language_names = {
            'en': {'name': 'English', 'native': 'English'},
            'zh': {'name': 'Chinese', 'native': '中文'}
        }
        
        return language_names.get(lang_code, {
            'name': lang_code.upper(),
            'native': lang_code.upper()
        })


# Global instance
language_manager = LanguageManager()


def init_i18n(app):
    """Initialize i18n support for the Flask application."""
    language_manager.init_app(app)
    return language_manager


# Template helper functions
def _(key: str, **kwargs) -> str:
    """Shorthand translation function for use in templates and code."""
    return language_manager.translate(key, **kwargs)


def get_locale() -> str:
    """Get the current locale."""
    return language_manager.get_locale()


def set_locale(lang_code: str) -> bool:
    """Set the current locale."""
    return language_manager.set_locale(lang_code)
