/**
 * Fichier  : assets/js/i18n.js
 * Auteur   : KREMER Régis
 * Version  : 2.6.73
 * Date     : 2026-07-11
 * Description : Noyau i18n, langue utilisateur, locale régionale et devise entreprise
 *
 * Changelog :
 *   v2.6.10 — Langue PHP prioritaire, changement avec rechargement et APP_BASE_PATH.
 *   v2.6.70 — I18N CORE LOCALE CURRENCY1 : Intl centralisé, devise configurable sans conversion et interpolation des traductions.
 *   v2.6.72 — I18N MODULES COMPLETE ROLLBACK1 : retour au moteur explicite stable, sans balayage DOM global ni observer sémantique.
 *   v2.6.73 — I18N MODULES SAFE ARCHI1 : socle explicite conservé, aucun observer global.
 */
(function(){
  'use strict';

  const SUPPORTED = ['fr','en','de','es','it','nl','pt','pl','ru','tr','ar','ja','ko','zh','hi','id','uk'];
  const RTL_LANGS = ['ar'];
  const LANG_LOCALES = {
    fr:'fr-FR', en:'en-GB', de:'de-DE', es:'es-ES', it:'it-IT', nl:'nl-NL', pt:'pt-PT',
    pl:'pl-PL', ru:'ru-RU', tr:'tr-TR', ar:'ar-SA', ja:'ja-JP', ko:'ko-KR', zh:'zh-CN',
    hi:'hi-IN', id:'id-ID', uk:'uk-UA'
  };

  const FLAGS = {
    fr:'🇫🇷', en:'🇬🇧', de:'🇩🇪', es:'🇪🇸', it:'🇮🇹', nl:'🇳🇱', pt:'🇵🇹', pl:'🇵🇱',
    ru:'🇷🇺', tr:'🇹🇷', ar:'🇸🇦', ja:'🇯🇵', ko:'🇰🇷', zh:'🇨🇳', hi:'🇮🇳', id:'🇮🇩', uk:'🇺🇦'
  };

  const NAMES = {
    fr:'Français', en:'English', de:'Deutsch', es:'Español', it:'Italiano', nl:'Nederlands',
    pt:'Português', pl:'Polski', ru:'Русский', tr:'Türkçe', ar:'العربية', ja:'日本語',
    ko:'한국어', zh:'中文', hi:'हिन्दी', id:'Bahasa Indonesia', uk:'Українська'
  };

  function runtime(){ return window.MageStockRuntime || {}; }

  function runtimeUrl(path){
    const raw = String(path || '');
    if(/^(?:https?:)?\/\//i.test(raw) || raw.charAt(0) === '/') return raw;
    const base = String(runtime().basePath || '').replace(/\/+$/, '');
    return (base ? base : '') + '/' + raw.replace(/^\.\//, '').replace(/^\/+/, '');
  }

  function runtimeCookiePath(){ return runtime().cookiePath || runtime().basePath || '/'; }

  function detectLang(){
    if(window._SM_LANG_PHP && SUPPORTED.includes(window._SM_LANG_PHP)) return window._SM_LANG_PHP;
    const stored = localStorage.getItem('sm_lang');
    return stored && SUPPORTED.includes(stored) ? stored : 'fr';
  }

  function normalizeLocale(locale){
    const raw = String(locale || '').replace('_','-').trim();
    if(raw && raw !== 'auto') {
      try { return Intl.getCanonicalLocales(raw)[0] || raw; } catch(_e) { /* fallback below */ }
    }
    return LANG_LOCALES[window.SM_LANG] || 'fr-FR';
  }

  function normalizeCurrency(currency){
    const code = String(currency || 'EUR').trim().toUpperCase();
    return /^[A-Z]{3}$/.test(code) ? code : 'EUR';
  }

  function finiteNumber(value, fallback = 0){
    const number = Number(value);
    return Number.isFinite(number) ? number : fallback;
  }

  function validDate(value){
    if(value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
    if(value === null || value === undefined || value === '') return null;
    const date = new Date(value);
    return Number.isNaN(date.getTime()) ? null : date;
  }

  window.SM_LANG = detectLang();
  window.SM_I18N = {};

  const configuredLocale = runtime().configuredLocale || runtime().locale || runtime().effectiveLocale || 'auto';
  const effectiveLocale = normalizeLocale(configuredLocale);
  const currency = normalizeCurrency(runtime().currency || 'EUR');
  const country = String(runtime().country || 'FR').toUpperCase();

  const Locale = {
    language: window.SM_LANG,
    configuredLocale,
    locale: effectiveLocale,
    currency,
    country,

    formatNumber(value, options = {}){
      const number = finiteNumber(value);
      try { return new Intl.NumberFormat(this.locale, options).format(number); }
      catch(_e) { return String(number); }
    },

    formatInteger(value, options = {}){
      return this.formatNumber(value, { maximumFractionDigits:0, ...options });
    },

    formatDecimal(value, digits = 2, options = {}){
      return this.formatNumber(value, {
        minimumFractionDigits:digits,
        maximumFractionDigits:digits,
        ...options
      });
    },

    formatMoney(value, options = {}){
      const number = finiteNumber(value);
      const selectedCurrency = normalizeCurrency(options.currency || this.currency);
      const intlOptions = { ...options };
      delete intlOptions.empty;
      delete intlOptions.currency;
      Object.assign(intlOptions, {
        style:'currency',
        currency:selectedCurrency,
        currencyDisplay:options.currencyDisplay || 'symbol'
      });
      try { return new Intl.NumberFormat(this.locale, intlOptions).format(number); }
      catch(_e) { return this.formatDecimal(number, 2) + ' ' + selectedCurrency; }
    },

    formatMoneyOrDash(value, options = {}){
      const number = Number(value);
      if(!Number.isFinite(number) || (options.emptyZero && number === 0)) return options.empty || '—';
      const copy = {...options};
      delete copy.emptyZero;
      delete copy.empty;
      return this.formatMoney(number, copy);
    },

    formatMoneyCompact(value, options = {}){
      return this.formatMoney(value, {
        notation:'compact',
        compactDisplay:'short',
        maximumFractionDigits:1,
        ...options
      });
    },

    currencySymbol(currencyCode = this.currency){
      try {
        const part = new Intl.NumberFormat(this.locale, {style:'currency', currency:normalizeCurrency(currencyCode), currencyDisplay:'narrowSymbol'})
          .formatToParts(0).find(item => item.type === 'currency');
        return part ? part.value : normalizeCurrency(currencyCode);
      } catch(_e) { return normalizeCurrency(currencyCode); }
    },

    currencyCode(){ return this.currency; },

    displayName(type, code, fallback = ''){
      try {
        if(typeof Intl.DisplayNames === 'function'){
          return new Intl.DisplayNames([this.locale], {type}).of(code) || fallback || code;
        }
      } catch(_e) { /* fallback below */ }
      return fallback || code;
    },

    displayRegion(code, fallback = ''){ return this.displayName('region', String(code || '').toUpperCase(), fallback); },
    displayCurrency(code, fallback = ''){ return this.displayName('currency', normalizeCurrency(code), fallback); },
    displayLanguage(code, fallback = ''){ return this.displayName('language', String(code || '').toLowerCase(), fallback); },

    displayLocale(localeCode, fallback = ''){
      const normalized = normalizeLocale(localeCode);
      const parts = normalized.split('-');
      const language = this.displayLanguage(parts[0], parts[0]);
      const region = parts[1] ? this.displayRegion(parts[1], parts[1]) : '';
      return region ? language + ' — ' + region : (language || fallback || normalized);
    },

    formatDate(value, options = {}){
      const date = validDate(value);
      if(!date) return options.empty || '—';
      const intlOptions = {...options};
      delete intlOptions.empty;
      if(Object.keys(intlOptions).length === 0){
        Object.assign(intlOptions, {day:'2-digit', month:'2-digit', year:'numeric'});
      }
      try { return new Intl.DateTimeFormat(this.locale, intlOptions).format(date); }
      catch(_e) { return date.toISOString().slice(0,10); }
    },

    formatDateTime(value, options = {}){
      const date = validDate(value);
      if(!date) return options.empty || '—';
      const intlOptions = {
        day:'2-digit', month:'2-digit', year:'numeric', hour:'2-digit', minute:'2-digit',
        ...options
      };
      delete intlOptions.empty;
      try { return new Intl.DateTimeFormat(this.locale, intlOptions).format(date); }
      catch(_e) { return date.toISOString(); }
    },

    formatTime(value, options = {}){
      const date = validDate(value);
      if(!date) return options.empty || '—';
      const intlOptions = { hour:'2-digit', minute:'2-digit', ...options };
      delete intlOptions.empty;
      try { return new Intl.DateTimeFormat(this.locale, intlOptions).format(date); }
      catch(_e) { return date.toTimeString().slice(0,5); }
    },

    formatPercent(value, options = {}){
      return this.formatNumber(value, {style:'percent', maximumFractionDigits:1, ...options});
    },

    inputLabel(label){ return String(label || '') + ' (' + this.currencyCode() + ')'; }
  };

  window.Locale = Locale;
  window.SM_LOCALE = Locale.locale;
  window.SM_CURRENCY = Locale.currency;

  function interpolate(value, params){
    if(!params || typeof params !== 'object') return value;
    return String(value).replace(/\{([a-zA-Z0-9_.-]+)\}/g, function(match, key){
      return Object.prototype.hasOwnProperty.call(params, key) ? String(params[key]) : match;
    });
  }

  window.t = function(key, params, fallback){
    if(typeof params === 'string' && fallback === undefined){ fallback = params; params = null; }
    const has = Object.prototype.hasOwnProperty.call(window.SM_I18N, key);
    const candidate = has ? window.SM_I18N[key] : null;
    const usable = typeof candidate === 'string' && candidate.trim() !== '' && !/^__TODO__(?:__)?$/i.test(candidate.trim());
    const value = usable ? candidate : (fallback !== undefined ? fallback : key);
    return interpolate(value, params);
  };

  window.applyI18n = function(root){
    // Architecture sûre : uniquement une racine de module explicite.
    // Le document complet n’est jamais parcouru automatiquement.
    if(!root || root === document) return;
    const semantic = [];
    if(root.nodeType === Node.ELEMENT_NODE && root.matches('[data-i18n]')) semantic.push(root);
    if(root.querySelectorAll) root.querySelectorAll('[data-i18n]').forEach(el => semantic.push(el));
    semantic.forEach(function(el){
      const key = el.getAttribute('data-i18n');
      const fallback = el.getAttribute('data-i18n-fallback') || el.textContent || '';
      if(!key) return;
      const translated = window.t(key, fallback);
      if(el.textContent !== translated) el.textContent = translated;
    });
    const attrs = [
      ['data-i18n-placeholder','placeholder'], ['data-i18n-title','title'],
      ['data-i18n-aria-label','aria-label'], ['data-i18n-alt','alt']
    ];
    attrs.forEach(function(pair){
      const elements=[];
      if(root.nodeType === Node.ELEMENT_NODE && root.matches('['+pair[0]+']')) elements.push(root);
      if(root.querySelectorAll) root.querySelectorAll('['+pair[0]+']').forEach(el => elements.push(el));
      elements.forEach(function(el){
        const key = el.getAttribute(pair[0]);
        if(!key) return;
        const translated = window.t(key, el.getAttribute(pair[1]) || '');
        if(el.getAttribute(pair[1]) !== translated) el.setAttribute(pair[1], translated);
      });
    });
    document.documentElement.lang = window.SM_LANG;
    document.documentElement.dir = RTL_LANGS.includes(window.SM_LANG) ? 'rtl' : 'ltr';
  };

  window.setLang = function(lang){
    if(!SUPPORTED.includes(lang)) return Promise.reject(new Error('Lang not supported: ' + lang));
    if(lang === window.SM_LANG) return Promise.resolve();
    const flag = document.getElementById('langFlag');
    if(flag) flag.textContent = FLAGS[lang] || '🌐';
    const expires = new Date(Date.now() + 365*24*3600*1000).toUTCString();
    document.cookie = 'sm_lang=' + encodeURIComponent(lang)
      + ';path=' + runtimeCookiePath() + ';expires=' + expires + ';SameSite=Lax';
    localStorage.setItem('sm_lang', lang);
    fetch(runtimeUrl('api/lang.php'), {
      method:'POST',
      headers:{'Content-Type':'application/json','X-CSRF-Token':window.CSRF_TOKEN || ''},
      body:JSON.stringify({lang})
    }).catch(function(){});
    return new Promise(function(resolve){ setTimeout(function(){ location.reload(); resolve(); }, 80); });
  };

  window._i18nReady = fetch(runtimeUrl('api/lang.php?lang=' + encodeURIComponent(window.SM_LANG) + '&v=' + encodeURIComponent(runtime().version || '')))
    .then(function(response){
      if(!response.ok) throw new Error('Translation HTTP ' + response.status);
      return response.json();
    })
    .then(function(data){
      window.SM_I18N = data && typeof data === 'object' ? data : {};
      document.documentElement.lang = window.SM_LANG;
      document.documentElement.dir = RTL_LANGS.includes(window.SM_LANG) ? 'rtl' : 'ltr';
      const flag = document.getElementById('langFlag');
      if(flag) flag.textContent = FLAGS[window.SM_LANG] || '🌐';
    })
    .catch(function(){
      document.documentElement.lang = window.SM_LANG;
      document.documentElement.dir = RTL_LANGS.includes(window.SM_LANG) ? 'rtl' : 'ltr';
    });

  window.I18N = {
    SUPPORTED, FLAGS, NAMES, RTL_LANGS, LANG_LOCALES,
    Locale,
    t:window.t,
    apply:window.applyI18n
  };
})();
