/*
 * @intranet-file styles/js/table_sort.js
 * @intranet-file-version 2026.03.13.1
 * @intranet-file-date 2026-03-13
 * @intranet-file-owner CSIF Intranet
 */
/*
  IntraTableSort - Ordenación de tablas (cliente) con estilo unificado.
  Uso:
    - Añade class="table-sortable" a la tabla.
    - En <th> opcional: data-sort-type="text|num|date".
    - En <td> opcional: data-sort="valor" (prioritario para ordenar).
    - Llama: IntraTableSort.makeSortable('#miTabla') o IntraTableSort.makeAll();
*/
(function(){
  'use strict';

  function normText(v){
    return (v ?? '').toString().trim();
  }

  function parseNum(v){
    const t = normText(v).replace(/\s+/g,'');
    // Normaliza miles 1.234 -> 1234 y decimal 1,23 -> 1.23
    const n = Number(t.replace(/[^0-9,.-]/g,'').replace(/\.(?=\d{3}(\D|$))/g,'').replace(',', '.'));
    return Number.isFinite(n) ? n : NaN;
  }

  function parseDate(v){
    const t = normText(v);
    if(!t) return NaN;
    // Soporta: YYYY-MM-DD, YYYY-MM-DD HH:MM, DD/MM/YYYY, DD/MM/YYYY HH:MM
    let m;
    m = t.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/);
    if(m){
      const y=+m[1], mo=+m[2]-1, d=+m[3], hh=+(m[4]||0), mm=+(m[5]||0), ss=+(m[6]||0);
      return new Date(y,mo,d,hh,mm,ss).getTime();
    }
    m = t.match(/^(\d{2})\/(\d{2})\/(\d{4})(?:\s+(\d{2}):(\d{2})(?::(\d{2}))?)?$/);
    if(m){
      const d=+m[1], mo=+m[2]-1, y=+m[3], hh=+(m[4]||0), mm=+(m[5]||0), ss=+(m[6]||0);
      return new Date(y,mo,d,hh,mm,ss).getTime();
    }
    const ts = Date.parse(t);
    return Number.isFinite(ts) ? ts : NaN;
  }

  function getCellSortValue(td){
    if(!td) return '';
    if(td.dataset && td.dataset.sort != null) return td.dataset.sort;
    return td.innerText ?? '';
  }

  function compare(a, b, type){
    if(type === 'num'){
      const na = parseNum(a), nb = parseNum(b);
      if(Number.isFinite(na) && Number.isFinite(nb)) return na - nb;
    }
    if(type === 'date'){
      const da = parseDate(a), db = parseDate(b);
      if(Number.isFinite(da) && Number.isFinite(db)) return da - db;
    }
    const ta = normText(a);
    const tb = normText(b);
    return ta.localeCompare(tb, 'es', {numeric:true, sensitivity:'base'});
  }

  function makeSortable(table){
    if(!table) return;
    if(typeof table === 'string') table = document.querySelector(table);
    if(!table) return;

    const thead = table.querySelector('thead');
    const tbody = table.querySelector('tbody');
    if(!thead || !tbody) return;

    const ths = Array.from(thead.querySelectorAll('th'));
    ths.forEach((th, idx) => {
      th.classList.add('th-sortable');
      th.setAttribute('role','button');
      th.setAttribute('tabindex','0');
      th.title = 'Ordenar';

      const handler = () => {
        const cur = th.getAttribute('data-sort-dir');
        const next = (cur === 'asc') ? 'desc' : 'asc';
        ths.forEach(x => x.removeAttribute('data-sort-dir'));
        th.setAttribute('data-sort-dir', next);

        const type = (th.dataset && th.dataset.sortType) ? th.dataset.sortType : 'text';
        const rows = Array.from(tbody.querySelectorAll('tr'));

        rows.sort((ra, rb) => {
          const ca = ra.children[idx];
          const cb = rb.children[idx];
          const va = getCellSortValue(ca);
          const vb = getCellSortValue(cb);
          const cmp = compare(va, vb, type);
          return next === 'asc' ? cmp : -cmp;
        });

        rows.forEach(r => tbody.appendChild(r));
      };

      th.addEventListener('click', handler);
      th.addEventListener('keydown', (e) => {
        if(e.key === 'Enter' || e.key === ' '){
          e.preventDefault();
          handler();
        }
      });
    });
  }

  function makeAll(){
    document.querySelectorAll('table.table-sortable').forEach(makeSortable);
  }

  window.IntraTableSort = { makeSortable, makeAll };
  document.addEventListener('DOMContentLoaded', makeAll);
})();
