import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
import '../theme/locale_controller.dart';

/// Hand-rolled translation dictionary loaded from flat JSON files in
/// `assets/lang/`, one per language — freely hand-editable, no codegen.
/// All dictionaries are preloaded at startup since they're tiny, so [t]
/// is a pure synchronous lookup with no async gap on language switch.
class AppStrings {
  AppStrings._();

  static const supportedLocales = ['en', 'ms', 'zh'];
  static final Map<String, Map<String, String>> _dictionaries = {};

  static Future<void> preloadAll() async {
    for (final code in supportedLocales) {
      final raw = await rootBundle.loadString('assets/lang/$code.json');
      _dictionaries[code] = Map<String, String>.from(json.decode(raw));
    }
  }

  /// Looks up [key] in the active locale, falling back to English, then
  /// to the raw key itself — a missing translation is loud, not silent.
  static String t(String key) {
    final code = LocaleController.localeCode.value;
    return _dictionaries[code]?[key] ?? _dictionaries['en']?[key] ?? key;
  }

  /// Like [t], but replaces `{placeholder}` tokens with [params] — for
  /// strings with dynamic content (counts, timestamps, error messages).
  static String tp(String key, Map<String, String> params) {
    var result = t(key);
    for (final entry in params.entries) {
      result = result.replaceAll('{${entry.key}}', entry.value);
    }
    return result;
  }

  /// Display-only translation for an MPOB class name (e.g. "Ripe").
  /// The underlying data key (used for DB storage, color lookups, and
  /// tally maps) is never touched — this only affects what's shown on
  /// screen.
  static String className(String englishClassName) => t('class_$englishClassName');
}
