/**
 * @file
 * Client-side table sorting for the dashboard media table.
 */

(function (Drupal, once) {
  'use strict';

  /**
   * Adds sortable column headers to the media table.
   *
   * @type {Drupal~behavior}
   */
  Drupal.behaviors.ffmpegTableSort = {
    attach: function (context) {
      once('ffmpeg-table-sort', '.ffmpeg-media-table', context).forEach(function (table) {
        var thead = table.querySelector('thead');
        var tbody = table.querySelector('tbody');
        if (!thead || !tbody) {
          return;
        }

        var headers = thead.querySelectorAll('th');
        // Sortable column indices: Media (0), Bundle (1), Status (2), Updated (4).
        // Outputs (3) and Operations (5) are not sortable.
        var sortableIndices = [0, 1, 2, 4];

        headers.forEach(function (th, index) {
          if (sortableIndices.indexOf(index) === -1) {
            return;
          }

          th.classList.add('sortable');
          th.setAttribute('role', 'columnheader');
          th.setAttribute('aria-sort', 'none');
          th.setAttribute('tabindex', '0');
          th.style.cursor = 'pointer';
          th.title = Drupal.t('Sort by @column', {'@column': th.textContent.trim()});

          var indicator = document.createElement('span');
          indicator.className = 'sort-indicator';
          indicator.setAttribute('aria-hidden', 'true');
          th.appendChild(indicator);

          th.addEventListener('click', function () {
            sortTable(table, tbody, headers, index);
          });

          th.addEventListener('keydown', function (e) {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              sortTable(table, tbody, headers, index);
            }
          });
        });
      });
    }
  };

  /**
   * Sorts a table by column index.
   *
   * @param {HTMLTableElement} table - The table element.
   * @param {HTMLTableSectionElement} tbody - The table body.
   * @param {NodeList} headers - All header cells.
   * @param {number} columnIndex - Column to sort by.
   */
  function sortTable(table, tbody, headers, columnIndex) {
    var currentSort = headers[columnIndex].getAttribute('aria-sort');
    var direction = currentSort === 'ascending' ? 'descending' : 'ascending';

    // Reset all headers.
    headers.forEach(function (th) {
      th.setAttribute('aria-sort', 'none');
      var ind = th.querySelector('.sort-indicator');
      if (ind) {
        ind.textContent = '';
      }
    });

    // Set active sort.
    headers[columnIndex].setAttribute('aria-sort', direction);
    var activeIndicator = headers[columnIndex].querySelector('.sort-indicator');
    if (activeIndicator) {
      activeIndicator.textContent = direction === 'ascending' ? ' \u25B2' : ' \u25BC';
    }

    var rows = Array.from(tbody.querySelectorAll('tr'));
    var isDateColumn = columnIndex === 4;

    rows.sort(function (a, b) {
      var cellA = a.children[columnIndex];
      var cellB = b.children[columnIndex];
      if (!cellA || !cellB) {
        return 0;
      }

      var textA = getCellSortValue(cellA, isDateColumn);
      var textB = getCellSortValue(cellB, isDateColumn);

      var result;
      if (isDateColumn) {
        result = textA - textB;
      }
      else {
        result = textA.localeCompare(textB, undefined, {numeric: true, sensitivity: 'base'});
      }

      return direction === 'ascending' ? result : -result;
    });

    // Re-append in sorted order.
    var fragment = document.createDocumentFragment();
    rows.forEach(function (row) {
      fragment.appendChild(row);
    });
    tbody.appendChild(fragment);
  }

  /**
   * Gets the sortable value from a cell.
   *
   * @param {HTMLTableCellElement} cell - The table cell.
   * @param {boolean} isDate - Whether to parse as date.
   * @returns {string|number} The sort value.
   */
  function getCellSortValue(cell, isDate) {
    var text = cell.textContent.trim();

    if (isDate) {
      if (text === '' || text === '-') {
        return 0;
      }
      var timestamp = Date.parse(text);
      return isNaN(timestamp) ? 0 : timestamp;
    }

    return text.toLowerCase();
  }

})(Drupal, once);
