/**
 * Fichier  : assets/js/pages/dashboard.js
 * Version  : 2.6.73
 * Date     : 2026-07-11
 * Description : Tableau de bord, locale/devise et traductions explicites au rendu
 *
 * Changelog :
 *   v2.6.70 — Locale et devise centralisées.
 *   v2.6.73 — I18N MODULES SAFE ARCHI1 : appels t() directs, sans observer ni balayage DOM.
 */
const DashPage = {
  data: null,
  actPage: 1,
  actPerPage: 15,

  tr(key, fallback, params = {}){
    return typeof window.t === 'function' ? window.t(key, params, fallback) : fallback;
  },

  async init(){
    const [prods, stock, mvs, warehses, alerts, orders] = await Promise.all([
      Api.products(), Api.stock(), Api.movements(), Api.warehouses(), Api.alerts(), Api.orders().catch(()=>[])
    ]);
    this.data = { prods, stock, mvs, warehses, alerts, orders };
    this.renderKPIs();
    this.renderCharts();
    this.renderActivity();
    this.renderAlerts();
  },

  renderKPIs(){
    const { prods, stock, alerts, warehses, orders } = this.data;
    const totalProd = prods.length;
    const totalUnit = stock.reduce((sum,item)=>sum+(parseInt(item.quantity,10)||0), 0);
    const totalValue = stock.reduce((sum,item)=>{
      const product = prods.find(candidate=>String(candidate.id)===String(item.productId));
      return sum + (getBaseCost(product) * (parseInt(item.quantity,10)||0));
    }, 0);
    const alertCount = alerts.filter(alert=>alert.triggered).length;
    const ordersPending = (orders||[]).filter(order=>['draft','sent','partial'].includes(order.status)).length;
    const warehouseCount = warehses.length;

    const formatCompact = value => Locale.formatNumber(value, {notation:'compact', compactDisplay:'short', maximumFractionDigits:1});
    const formatMoney = value => Locale.formatMoneyCompact(value, {maximumFractionDigits:1});
    const cards = [
      {ico:'📦', val:formatCompact(totalProd), lbl:this.tr('dashboard.kpi.products','Produits'), c:'blue'},
      {ico:'🏷️', val:formatCompact(totalUnit), lbl:this.tr('dashboard.kpi.units_in_stock','Unités en stock'), c:'green'},
      {ico:'💰', val:formatMoney(totalValue), lbl:this.tr('dashboard.kpi.stock_value','Valeur du stock'), c:'orange'},
      {ico:'🔔', val:Locale.formatInteger(alertCount), lbl:this.tr('dashboard.kpi.active_alerts','Alertes actives'), c:alertCount>0?'red':'green'},
      {ico:'🛒', val:Locale.formatInteger(ordersPending), lbl:this.tr('dashboard.kpi.pending_orders','Commandes en cours'), c:ordersPending>0?'purple':'green'},
      {ico:'🏪', val:Locale.formatInteger(warehouseCount), lbl:this.tr('dashboard.kpi.warehouses','Magasins'), c:'cyan'},
    ];

    const target = document.getElementById('kpiRow');
    if(!target) return;
    target.innerHTML = cards.map(card=>`<div class="dash-kpi" data-c="${card.c}">
      <div class="dash-kpi-ico">${card.ico}</div>
      <div class="dash-kpi-val">${_esc(card.val)}</div>
      <div class="dash-kpi-lbl">${_esc(card.lbl)}</div>
    </div>`).join('');
  },

  renderCharts(){
    if(window.Chart){ this._chartMov(); this._chartVal(); }
  },

  _charts: {},
  _destroyChart(key){ try{ this._charts[key]?.destroy(); delete this._charts[key]; }catch(_error){} },

  _chartMov(){
    const canvas = document.getElementById('dashChartMov');
    if(!canvas) return;
    const movements = this.data.mvs||[];
    const today = new Date();
    const labels=[];
    const values=[];
    for(let index=13; index>=0; index--){
      const date=new Date(today);
      date.setDate(today.getDate()-index);
      const key=date.toISOString().slice(0,10);
      labels.push(Locale.formatDate(date,{day:'2-digit',month:'2-digit'}));
      values.push(movements.filter(movement=>(movement.createdAt||movement.date||'').slice(0,10)===key).length);
    }
    this._destroyChart('mov');
    this._charts.mov = new Chart(canvas.getContext('2d'), {
      type:'bar',
      data:{labels, datasets:[{label:this.tr('dashboard.chart.movements','Mouvements'),data:values,
        backgroundColor:'rgba(59,130,246,0.55)',borderColor:'rgba(59,130,246,0.9)',borderWidth:1,borderRadius:4}]},
      options:{responsive:true,maintainAspectRatio:false,
        scales:{y:{beginAtZero:true,ticks:{precision:0}},x:{ticks:{font:{size:10}}}},
        plugins:{legend:{display:false}}}
    });
  },

  _chartVal(){
    const canvas = document.getElementById('dashChartVal');
    if(!canvas) return;
    const {prods=[],stock=[],warehses=[]} = this.data;
    const byWarehouse={};
    for(const item of stock){
      const product=prods.find(candidate=>String(candidate.id)===String(item.productId));
      const warehouseId=String(item.warehouseId||'');
      byWarehouse[warehouseId] = (byWarehouse[warehouseId]||0) + getBaseCost(product)*(parseFloat(item.quantity)||0);
    }
    const labels=[];
    const values=[];
    const colors=[];
    const palette=['rgba(59,130,246,0.6)','rgba(16,185,129,0.6)','rgba(245,158,11,0.6)','rgba(239,68,68,0.6)','rgba(139,92,246,0.6)','rgba(236,72,153,0.6)'];
    let colorIndex=0;
    for(const warehouse of warehses){
      labels.push(warehouse.name||this.tr('dashboard.warehouse_fallback','Magasin {id}',{id:warehouse.id}));
      values.push(parseFloat((byWarehouse[String(warehouse.id)]||0).toFixed(2)));
      colors.push(palette[colorIndex++%palette.length]);
    }
    this._destroyChart('val');
    this._charts.val = new Chart(canvas.getContext('2d'), {
      type:'bar',
      data:{labels, datasets:[{label:this.tr('dashboard.chart.value_currency','Valeur ({currency})',{currency:Locale.currencyCode()}),data:values,backgroundColor:colors,borderColor:colors.map(color=>color.replace('0.6','0.9')),borderWidth:1,borderRadius:4}]},
      options:{responsive:true,maintainAspectRatio:false,
        scales:{y:{beginAtZero:true},x:{ticks:{font:{size:10}}}},
        plugins:{legend:{display:false},tooltip:{callbacks:{label:context=>Locale.formatMoney(context.raw||0)}}}}
    });
  },

  renderActivity(){
    const target = document.getElementById('activityFeed');
    const footer = document.getElementById('activityFooter');
    if(!target) return;

    const allMovements = [...(this.data.mvs||[])].sort((a,b)=>new Date(b.date)-new Date(a.date));
    const totalPages = Math.max(1, Math.ceil(allMovements.length/this.actPerPage));
    if(this.actPage > totalPages) this.actPage = totalPages;
    const page = allMovements.slice((this.actPage-1)*this.actPerPage, this.actPage*this.actPerPage);
    const products = this.data.prods;

    if(!page.length){
      target.innerHTML = `<div class="dash-act-empty">${_esc(this.tr('dashboard.activity.none','Aucune activité'))}</div>`;
      if(footer) footer.innerHTML = '';
      return;
    }

    const icons = {add:'➕',remove:'📤',transfer:'🔄',entry:'📥',inventory:'📋'};
    const typeKeys = {
      add:['dashboard.movement.add','Ajout'],
      remove:['dashboard.movement.remove','Sortie'],
      transfer:['dashboard.movement.transfer','Transfert'],
      entry:['dashboard.movement.entry','Entrée'],
      inventory:['dashboard.movement.inventory','Inventaire']
    };

    target.innerHTML = page.map(movement=>{
      const product = products.find(candidate=>String(candidate.id)===String(movement.productId));
      const name = product ? product.name : '?';
      const date = new Date(movement.date);
      const time = Locale.formatDate(date,{day:'2-digit',month:'short'}) + ' ' + Locale.formatTime(date,{hour:'2-digit',minute:'2-digit'});
      const icon = icons[movement.type]||'📦';
      const typeConfig = typeKeys[movement.type];
      const typeLabel = typeConfig ? this.tr(typeConfig[0],typeConfig[1]) : String(movement.type||'');
      const quantity = this.tr('dashboard.unit.short','{value} u',{value:Locale.formatNumber(movement.quantity||0)});
      const title = this.tr('dashboard.activity.title','{name} — {type} ({quantity})',{
        name:_esc(name), type:_esc(typeLabel), quantity:_esc(quantity)
      });
      return `<div class="dash-act">
        <div class="dash-act-ico ${_esc(movement.type||'')}">${icon}</div>
        <div class="dash-act-body">
          <div class="dash-act-title">${title}</div>
          <div class="dash-act-meta">${_esc(movement.operator||'?')}${movement.site?' · '+_esc(movement.site):''}</div>
        </div>
        <div class="dash-act-time">${_esc(time)}</div>
      </div>`;
    }).join('');

    if(footer && totalPages > 1){
      footer.innerHTML = `
        <button class="dash-pg-btn" onclick="DashPage.actPrev()" ${this.actPage<=1?'disabled':''}>${_esc(this.tr('dashboard.pagination.previous','◀ Précédent'))}</button>
        <span class="dash-pg-info">${_esc(this.tr('dashboard.pagination.page','Page {current} / {total}',{current:this.actPage,total:totalPages}))}</span>
        <button class="dash-pg-btn" onclick="DashPage.actNext(${totalPages})" ${this.actPage>=totalPages?'disabled':''}>${_esc(this.tr('dashboard.pagination.next','Suivant ▶'))}</button>
      `;
    } else if(footer) {
      footer.innerHTML = '';
    }
  },

  actPrev(){ if(this.actPage>1){ this.actPage--; this.renderActivity(); } },
  actNext(max){ if(this.actPage<max){ this.actPage++; this.renderActivity(); } },

  renderAlerts(){
    const triggered = this.data.alerts.filter(alert=>alert.triggered);
    const products = this.data.prods;
    const warehouses = this.data.warehses;
    const target = document.getElementById('alertsWidget');
    if(!target) return;

    if(!triggered.length){
      target.innerHTML = `<div class="dash-alerts-ok">
        <svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
          <path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
        </svg><span>${_esc(this.tr('dashboard.alerts.all_ok','Tout est en ordre'))}</span></div>`;
      return;
    }

    target.style.maxHeight = '380px';
    target.style.overflowY = 'auto';
    target.innerHTML = triggered.map(alert=>{
      const product = products.find(candidate=>String(candidate.id)===String(alert.productId));
      const warehouse = warehouses.find(candidate=>String(candidate.id)===String(alert.warehouseId));
      const name = product?.name||'?';
      const sku = product?.sku||'';
      const quantity = alert.currentQty??'?';
      const threshold = alert.threshold;
      const isMinimum = alert.type==='min';
      const imageSource = product?.image ? product.image : null;
      const imageHtml = imageSource
        ? `<img src="${_esc(imageSource)}" class="dash-alert-img" onerror="this.style.display='none';this.nextElementSibling.style.display='flex'" alt="">` +
          `<div class="dash-alert-img-fallback" style="display:none">${Icons.box}</div>`
        : `<div class="dash-alert-img-fallback">${Icons.box}</div>`;
      const badgeClass = isMinimum ? 'dash-alert-badge-min' : 'dash-alert-badge-max';
      const badgeLabel = isMinimum
        ? this.tr('dashboard.alerts.badge_min','↓ MIN')
        : this.tr('dashboard.alerts.badge_max','↑ MAX');
      const quantityLabel = Number.isFinite(Number(quantity)) ? Locale.formatNumber(Number(quantity)) : '?';
      const thresholdLabel = Number.isFinite(Number(threshold)) ? Locale.formatNumber(Number(threshold)) : '?';
      const detail = this.tr('dashboard.alerts.stock_detail','Stock : <strong>{qty}</strong> / seuil <strong>{threshold}</strong>',{
        qty:_esc(quantityLabel), threshold:_esc(thresholdLabel)
      });
      return `<div class="dash-alert-card">
        <div class="dash-alert-thumb">${imageHtml}</div>
        <div class="dash-alert-body">
          <div class="dash-alert-header"><span class="dash-alert-name">${_esc(name)}</span><span class="dash-alert-badge ${badgeClass}">${_esc(badgeLabel)}</span></div>
          ${sku?`<div class="dash-alert-sku">${_esc(sku)}</div>`:''}
          ${warehouse?`<div class="dash-alert-wh">${_esc(warehouse.name)}</div>`:''}
          <div class="dash-alert-detail">${detail}</div>
        </div>
      </div>`;
    }).join('');
  },
};

function _esc(value){
  return String(value??'').replace(/[&<>"']/g,character=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[character]));
}
