"""Internationalization (i18n) module for Trading Strategy Tester.

Provides a translation engine supporting multiple languages (RU/EN).
All UI strings, analysis results, and notifications are fully translatable.
"""

from __future__ import annotations

import json
import os
from typing import Any, Dict, List, Optional


# ---------------------------------------------------------------------------
# Supported languages
# ---------------------------------------------------------------------------
SUPPORTED_LOCALES = ("ru", "en")
DEFAULT_LOCALE = "ru"


# ---------------------------------------------------------------------------
# Translation dictionaries
# ---------------------------------------------------------------------------

# English (en) - base language
EN: Dict[str, str] = {
    # --- App / General ---
    "app_name": "Trading Strategy Tester",
    "app_version": "Version {version}",
    "loading": "Loading...",
    "system_ready": "System ready. Load data to begin.",
    "results_cleared": "Results cleared. System ready.",
    "loading_data": "Loading {count} candles for {instrument}/{tf}...",
    "data_loaded": "Loaded {count} candles for {instrument}/{tf}",
    "no_data": "No candle data returned",
    "analysis_complete": "Analysis complete: {direction} (confidence: {confidence}%)",
    "backtest_complete": "Backtest complete: {trades} trades, P&L: {pnl}",
    "range_backtest_complete": "Range backtest complete: {trades} trades, P&L: {pnl}",
    "backtest_started": "Running backtest: {instrument}/{tf}, {count} candles...",
    "range_backtest_started": "Range backtest: {start} → {end}",
    "analysis_started": "Running analysis...",
    "ml_trend_query": "Querying ML trend prediction...",
    "ml_patterns_query": "Querying ML pattern recognition...",
    "ml_trend_result": "ML Trend: {direction} (confidence: {confidence}%)",
    "ml_patterns_result": "ML Patterns: {patterns}",
    "ml_no_patterns": "No ML patterns detected",
    "ml_unavailable": "ML model not available",
    "cache_cleared": "Cache cleared successfully",

    # --- Connection / Status ---
    "db_status": "DB",
    "db_status_ok": "{status} ✓",
    "db_status_fail": "{status} ✗",
    "ml_status": "ML",
    "ml_status_available": "{status} ✓",
    "ml_status_unavailable": "{status} ○",
    "health_ok": "Status OK",

    # --- Sidebar Panels ---
    "panel_connection": "Connection",
    "panel_strategy": "Strategy Parameters",
    "panel_backtest": "Backtest",
    "panel_signal": "Signal",
    "panel_risk": "Risk Management",
    "panel_support_resistance": "Support / Resistance",
    "panel_ml": "ML Tools",
    "panel_cache": "Cache",
    "panel_analysis": "Analysis Log",
    "panel_results": "Backtest Results",
    "panel_trend": "Trend & Indicators",
    "panel_equity": "Equity Curve",
    "panel_price_chart": "Price Chart",

    # --- Labels / Inputs ---
    "label_instrument": "Instrument",
    "label_timeframe": "Timeframe",
    "label_max_candles": "Max Candles",
    "label_short_sma": "Short SMA",
    "label_long_sma": "Long SMA",
    "label_account_balance": "Account Balance ($)",
    "label_risk_percent": "Risk per trade (%)",
    "label_tp_multiplier": "TP Multiplier",
    "label_start_date": "Start Date",
    "label_end_date": "End Date",
    "label_candle_count": "Candles",

    # --- Button Labels ---
    "btn_load": "Load Data",
    "btn_analyze": "Analyze",
    "btn_clear": "Clear",
    "btn_backtest": "Quick Backtest",
    "btn_backtest_range": "Range Backtest",
    "btn_ml_trend": "ML Trend",
    "btn_ml_patterns": "ML Patterns",
    "btn_clear_cache": "Clear Cache",

    # --- Tooltips ---
    "tooltip_short_sma": "Short-term moving average period",
    "tooltip_long_sma": "Long-term moving average period",
    "tooltip_risk_percent": "Maximum percentage of account to risk per trade",
    "tooltip_tp_multiplier": "Take profit distance = SL distance × multiplier",

    # --- Signal Display ---
    "signal_waiting": "Waiting...",
    "signal_click_analyze": "Click Analyze to detect entry signals",
    "signal_no_signal": "No Signal",
    "signal_no_entry": "No entry signal detected",
    "signal_buy": "BUY",
    "signal_sell": "SELL",
    "signal_price": "Price: {price}",
    "signal_confidence": "Confidence: {confidence}%",
    "signal_stop_loss": "Stop Loss: {sl}",
    "signal_take_profit": "Take Profit: {tp}",
    "signal_pattern": "Pattern: {pattern}",
    "signal_trend_based": "trend-based",
    "signal_reason": "{reason}",

    # --- Trend Display ---
    "trend_direction": "Direction",
    "trend_strength": "Strength",
    "trend_confidence": "Confidence",
    "trend_slope": "Slope",
    "trend_rsi": "RSI",
    "trend_sma_short": "SMA Short",
    "trend_sma_long": "SMA Long",
    "trend_uptrend": "uptrend",
    "trend_downtrend": "downtrend",
    "trend_neutral": "neutral",

    # --- Risk Management ---
    "risk_entry_price": "Entry Price",
    "risk_stop_loss": "Stop Loss",
    "risk_take_profit": "Take Profit",
    "risk_position_size": "Position Size",
    "risk_amount": "Risk Amount",
    "risk_reward_ratio": "Reward:Risk",
    "risk_invalid": "Invalid trade",
    "risk_no_signal": "No valid entry found",
    "risk_ratio": "{ratio}:1",

    # --- Support / Resistance ---
    "sr_no_levels": "No support/resistance levels detected",
    "sr_support": "Support",
    "sr_resistance": "Resistance",
    "sr_level": "{type}: {price}",

    # --- Backtest Results ---
    "bt_total_trades": "Total Trades",
    "bt_wins": "Wins",
    "bt_losses": "Losses",
    "bt_win_rate": "Win Rate",
    "bt_total_pnl": "Total P&L",
    "bt_max_drawdown": "Max Drawdown",
    "bt_sharpe_ratio": "Sharpe Ratio",
    "bt_final_balance": "Final Balance",
    "bt_profit": "+${amount}",
    "bt_loss": "-${amount}",
    "bt_win": "WIN",
    "bt_loss_label": "LOSS",
    "bt_long": "LONG",
    "bt_short": "SHORT",
    "bt_trade_log": "Trade Log",
    "bt_no_trades": "No trades executed",
    "bt_run_backtest": "Run a backtest to see trade history",
    "bt_running": "Running backtest...",

    # --- Equity Curve ---
    "equity_title": "Equity Curve Data",
    "equity_no_data": "Run a backtest to see equity curve data",
    "equity_step": "Step",
    "equity_action": "Action",
    "equity_balance": "Balance",
    "equity_pnl": "P&L",

    # --- Analysis Log ---
    "log_initialized": "System initialized. Load data to begin.",
    "log_clear": "Results cleared",
    "log_error": "Error",
    "log_warning": "Warning",
    "log_success": "Success",

    # --- Timeframe options ---
    "tf_d1": "D1",
    "tf_h1": "H1",
    "tf_w1": "W1",
    "tf_m15": "M15",
    "tf_m5": "M5",

    # --- Language switcher ---
    "lang_label": "Language",
    "lang_ru": "Русский",
    "lang_en": "English",

    # --- Error messages ---
    "error_not_enough_candles": "Not enough candles (need {count})",
    "error_invalid_dates": "Invalid date format. Use ISO 8601 (e.g., 2024-01-01T00:00:00)",
    "error_db_unavailable": "Database not available",
    "error_analysis": "Analysis failed: {message}",
    "error_backtest": "Backtest failed: {message}",
    "error_data_load": "Failed to load data: {message}",
    "error_instruments": "Failed to load instruments: {message}",
    "error_ml_trend": "ML trend prediction unavailable: {message}",
    "error_ml_patterns": "ML patterns unavailable: {message}",
}

# Russian (ru) translations
RU: Dict[str, str] = {
    # --- App / General ---
    "app_name": "Тестер торговых стратегий",
    "app_version": "Версия {version}",
    "loading": "Загрузка...",
    "system_ready": "Система готова. Загрузите данные для начала.",
    "results_cleared": "Результаты очищены. Система готова.",
    "loading_data": "Загрузка {count} свечей для {instrument}/{tf}...",
    "data_loaded": "Загружено {count} свечей для {instrument}/{tf}",
    "no_data": "Данные по свечам не получены",
    "analysis_complete": "Анализ завершён: {direction} (уверенность: {confidence}%)",
    "backtest_complete": "Бэктест завершён: {trades} сделок, P&L: {pnl}",
    "range_backtest_complete": "Бэктест за период завершён: {trades} сделок, P&L: {pnl}",
    "backtest_started": "Запуск бэктеста: {instrument}/{tf}, {count} свечей...",
    "range_backtest_started": "Бэктест за период: {start} → {end}",
    "analysis_started": "Запуск анализа...",
    "ml_trend_query": "Запрос предсказания тренда (ML)...",
    "ml_patterns_query": "Запуск распознавания паттернов (ML)...",
    "ml_trend_result": "ML Тренд: {direction} (уверенность: {confidence}%)",
    "ml_patterns_result": "ML Паттерны: {patterns}",
    "ml_no_patterns": "ML паттерны не обнаружены",
    "ml_unavailable": "ML модель недоступна",
    "cache_cleared": "Кэш успешно очищен",

    # --- Connection / Status ---
    "db_status": "БД",
    "db_status_ok": "{status} ✓",
    "db_status_fail": "{status} ✗",
    "ml_status": "ML",
    "ml_status_available": "{status} ✓",
    "ml_status_unavailable": "{status} ○",
    "health_ok": "Статус OK",

    # --- Sidebar Panels ---
    "panel_connection": "Соединение",
    "panel_strategy": "Параметры стратегии",
    "panel_backtest": "Бэктест",
    "panel_signal": "Сигнал",
    "panel_risk": "Управление рисками",
    "panel_support_resistance": "Поддержка / Сопротивление",
    "panel_ml": "ML инструменты",
    "panel_cache": "Кэш",
    "panel_analysis": "Журнал анализа",
    "panel_results": "Результаты бэктеста",
    "panel_trend": "Тренд и индикаторы",
    "panel_equity": "Кривая эквити",
    "panel_price_chart": "График цен",

    # --- Labels / Inputs ---
    "label_instrument": "Инструмент",
    "label_timeframe": "Таймфрейм",
    "label_max_candles": "Макс. свечей",
    "label_short_sma": "Короткая SMA",
    "label_long_sma": "Длинная SMA",
    "label_account_balance": "Баланс ($)",
    "label_risk_percent": "Риск на сделку (%)",
    "label_tp_multiplier": "Множ. взятия прибыли",
    "label_start_date": "Дата начала",
    "label_end_date": "Дата окончания",
    "label_candle_count": "Свечи",

    # --- Button Labels ---
    "btn_load": "Загрузить данные",
    "btn_analyze": "Анализировать",
    "btn_clear": "Очистить",
    "btn_backtest": "Быстрый бэктест",
    "btn_backtest_range": "Бэктест за период",
    "btn_ml_trend": "ML Тренд",
    "btn_ml_patterns": "ML Паттерны",
    "btn_clear_cache": "Очистить кэш",

    # --- Tooltips ---
    "tooltip_short_sma": "Период краткосрочной скользящей средней",
    "tooltip_long_sma": "Период долгосрочной скользящей средней",
    "tooltip_risk_percent": "Максимальный процент баланса на риск в одной сделке",
    "tooltip_tp_multiplier": "Дистанция фиксации прибыли = дистанция стоп-лосса × множитель",

    # --- Signal Display ---
    "signal_waiting": "Ожидание...",
    "signal_click_analyze": "Нажмите «Анализировать» для обнаружения точек входа",
    "signal_no_signal": "Нет сигнала",
    "signal_no_entry": "Точка входа не обнаружена",
    "signal_buy": "ПОКУПКА",
    "signal_sell": "ПРОДАЖА",
    "signal_price": "Цена: {price}",
    "signal_confidence": "Уверенность: {confidence}%",
    "signal_stop_loss": "Стоп-лосс: {sl}",
    "signal_take_profit": "Взятие прибыли: {tp}",
    "signal_pattern": "Паттерн: {pattern}",
    "signal_reason": "{reason}",

    # --- Trend Display ---
    "trend_direction": "Направление",
    "trend_strength": "Сила",
    "trend_confidence": "Уверенность",
    "trend_slope": "Наклон",
    "trend_rsi": "RSI",
    "trend_sma_short": "SMA Короткая",
    "trend_sma_long": "SMA Длинная",
    "trend_uptrend": "восходящий тренд",
    "trend_downtrend": "нисходящий тренд",
    "trend_neutral": "нейтральный",

    # --- Risk Management ---
    "risk_entry_price": "Цена входа",
    "risk_stop_loss": "Стоп-лосс",
    "risk_take_profit": "Взятие прибыли",
    "risk_position_size": "Размер позиции",
    "risk_amount": "Сумма риска",
    "risk_reward_ratio": "Прибыль/Риск",
    "risk_invalid": "Некорректная сделка",
    "risk_no_signal": "Действующая точка входа не найдена",
    "risk_ratio": "{ratio}:1",

    # --- Support / Resistance ---
    "sr_no_levels": "Уровни поддержки/сопротивления не обнаружены",
    "sr_support": "Поддержка",
    "sr_resistance": "Сопротивление",
    "sr_level": "{type}: {price}",

    # --- Backtest Results ---
    "bt_total_trades": "Всего сделок",
    "bt_wins": "Выигрыши",
    "bt_losses": "Поражения",
    "bt_win_rate": "Процент выигрышей",
    "bt_total_pnl": "Общий P&L",
    "bt_max_drawdown": "Макс. просадка",
    "bt_sharpe_ratio": "Коэф. Шарпа",
    "bt_final_balance": "Итоговый баланс",
    "bt_profit": "+{amount} $",
    "bt_loss": "-{amount} $",
    "bt_win": "ВЫИГРЫШ",
    "bt_loss_label": "ПОРАЖЕНИЕ",
    "bt_long": "LONG",
    "bt_short": "SHORT",
    "bt_trade_log": "Журнал сделок",
    "bt_no_trades": "Сделок не совершено",
    "bt_run_backtest": "Запустите бэктест для просмотра истории сделок",
    "bt_running": "Бэктест запущен...",

    # --- Equity Curve ---
    "equity_title": "Данные кривой эквити",
    "equity_no_data": "Запустите бэктест для просмотра кривой эквити",
    "equity_step": "Шаг",
    "equity_action": "Действие",
    "equity_balance": "Баланс",
    "equity_pnl": "P&L",

    # --- Analysis Log ---
    "log_initialized": "Система инициализирована. Загрузите данные для начала.",
    "log_clear": "Результаты очищены",
    "log_error": "Ошибка",
    "log_warning": "Предупреждение",
    "log_success": "Успех",

    # --- Timeframe options ---
    "tf_d1": "D1",
    "tf_h1": "H1",
    "tf_w1": "W1",
    "tf_m15": "M15",
    "tf_m5": "M5",

    # --- Language switcher ---
    "lang_label": "Язык",
    "lang_ru": "Русский",
    "lang_en": "English",

    # --- Error messages ---
    "error_not_enough_candles": "Недостаточно свечей (нужно {count})",
    "error_invalid_dates": "Неверный формат даты. Используйте ISO 8601 (напр. 2024-01-01T00:00:00)",
    "error_db_unavailable": "База данных недоступна",
    "error_analysis": "Ошибка анализа: {message}",
    "error_backtest": "Ошибка бэктеста: {message}",
    "error_data_load": "Ошибка загрузки данных: {message}",
    "error_instruments": "Ошибка загрузки инструментов: {message}",
    "error_ml_trend": "ML предсказание тренда недоступно: {message}",
    "error_ml_patterns": "ML паттерны недоступны: {message}",
}


# ---------------------------------------------------------------------------
# All supported locale dictionaries
# ---------------------------------------------------------------------------
LOCALES: Dict[str, Dict[str, str]] = {
    "en": EN,
    "ru": RU,
}


# ---------------------------------------------------------------------------
# Translation function (singleton pattern)
# ---------------------------------------------------------------------------

def get_locale() -> str:
    """Get current locale from config file, falling back to default."""
    config_path = os.path.join(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
        "config", "app_config.json"
    )
    try:
        with open(config_path) as f:
            config = json.load(f)
        locale = config.get("locale", DEFAULT_LOCALE)
        if locale in SUPPORTED_LOCALES:
            return locale
        return DEFAULT_LOCALE
    except Exception:
        return DEFAULT_LOCALE


def set_locale(locale: str) -> bool:
    """Set the active locale in the config file. Returns True on success."""
    if locale not in SUPPORTED_LOCALES:
        return False
    config_path = os.path.join(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
        "config", "app_config.json"
    )
    try:
        with open(config_path) as f:
            config = json.load(f)
        config["locale"] = locale
        with open(config_path, "w") as f:
            json.dump(config, f, indent=4)
        return True
    except Exception:
        return False


def t(key: str, locale: Optional[str] = None, **kwargs: Any) -> str:
    """
    Translate a key to the target locale with optional interpolation.

    Args:
        key: Translation key (e.g. "app_name", "signal_buy")
        locale: Target locale code. If None, reads from config.
        **kwargs: Interpolation values (e.g. count=5, instrument="BTC")

    Returns:
        Translated string with placeholders replaced.
    """
    if locale is None:
        locale = get_locale()

    locale_dict = LOCALES.get(locale, LOCALES[DEFAULT_LOCALE])
    text = locale_dict.get(key, key)

    # Replace named placeholders like {count}, {instrument}, etc.
    if kwargs:
        text = text.format(**kwargs)

    return text


def t_all(keys: List[str], locale: Optional[str] = None, **kwargs: Any) -> Dict[str, str]:
    """Translate a list of keys at once. Useful for batch API responses."""
    result = {}
    for key in keys:
        result[key] = t(key, locale, **kwargs)
    return result


# ---------------------------------------------------------------------------
# Export convenience functions
# ---------------------------------------------------------------------------

def get_supported_locales() -> List[str]:
    """Return list of supported locale codes."""
    return list(SUPPORTED_LOCALES)


def get_all_translations(locale: Optional[str] = None) -> Dict[str, str]:
    """Return the complete translation dictionary for a locale."""
    if locale is None:
        locale = get_locale()
    return dict(LOCALES.get(locale, LOCALES[DEFAULT_LOCALE]))


def format_locale_display(locale: str) -> str:
    """Get display name for a locale in its own language."""
    names = {
        "ru": "Русский",
        "en": "English",
    }
    return names.get(locale, locale)