/* Shared client-side sorting + pagination for admin AJAX tables. */
const AdminTable = {
  sort(arr, key, dir) {
    if (!key) return arr;
    return [...arr].sort((a, b) => {
      let x = a[key], y = b[key];
      if (x == null && y == null) return 0;
      if (x == null) return 1;
      if (y == null) return -1;
      if (typeof x === 'number' && typeof y === 'number') return (x - y) * dir;
      const nx = parseFloat(x), ny = parseFloat(y);
      if (!isNaN(nx) && !isNaN(ny) && String(nx) === String(x).trim() && String(ny) === String(y).trim())
        return (nx - ny) * dir;
      return String(x).localeCompare(String(y), undefined, { numeric: true }) * dir;
    });
  },

  paginate(arr, page, size) {
    const total = Math.max(1, Math.ceil(arr.length / size));
    const p = Math.min(Math.max(1, page), total);
    return { slice: arr.slice((p - 1) * size, p * size), total, page: p };
  },

  pager(el, page, total, go) {
    if (!el) return;
    if (total <= 1) { el.innerHTML = ''; return; }
    let h = '<button class="pg" ' + (page <= 1 ? 'disabled' : '') + ' data-go="' + (page - 1) + '">&lsaquo;</button>';
    for (let i = 1; i <= total; i++)
      h += '<button class="pg ' + (i === page ? 'active' : '') + '" data-go="' + i + '">' + i + '</button>';
    h += '<button class="pg" ' + (page >= total ? 'disabled' : '') + ' data-go="' + (page + 1) + '">&rsaquo;</button>';
    el.innerHTML = h;
    el.querySelectorAll('.pg').forEach(b => b.onclick = () => { if (!b.disabled) go(parseInt(b.dataset.go)); });
  },

  /* Reset all styled file boxes within a form to their empty state. */
  resetFileboxes(form) {
    if (!form) return;
    form.querySelectorAll('.filebox').forEach(box => {
      box.classList.remove('has-file');
      const lbl = box.querySelector('.filebox-label');
      if (lbl) lbl.textContent = lbl.dataset.placeholder || 'Choose file';
    });
  },

  /* Client-side text filter for server-rendered tables. */
  liveFilter(input, tbody) {
    if (!input || !tbody) return;
    input.addEventListener('input', () => {
      const q = input.value.trim().toLowerCase();
      tbody.querySelectorAll('tr').forEach(tr => {
        tr.style.display = (!q || tr.textContent.toLowerCase().includes(q)) ? '' : 'none';
      });
    });
  },

  attachSort(thead, state, onChange) {
    if (!thead) return;
    thead.querySelectorAll('th[data-sort]').forEach(th => {
      th.classList.add('sortable');
      th.onclick = () => {
        const k = th.dataset.sort;
        if (state.sortKey === k) state.sortDir *= -1; else { state.sortKey = k; state.sortDir = 1; }
        thead.querySelectorAll('th[data-sort]').forEach(t => t.removeAttribute('data-dir'));
        th.setAttribute('data-dir', state.sortDir > 0 ? 'asc' : 'desc');
        onChange();
      };
    });
  }
};

/* Updates a styled .filebox label/state when a file is chosen. */
function fileboxUpdate(input) {
  const box = input.closest('.filebox');
  if (!box) return;
  const lbl = box.querySelector('.filebox-label');
  if (input.files && input.files.length) {
    box.classList.add('has-file');
    if (lbl) lbl.textContent = input.files[0].name;
  } else {
    box.classList.remove('has-file');
    if (lbl) lbl.textContent = (lbl && lbl.dataset.placeholder) || 'Choose file';
  }
}
