(() => {
  const perf = window.AssetPerf;
  perf?.start('browser-state:gesamtes Modul');
  const persistent = document.body?.dataset.persistBrowserState === 'true';
  const storage = persistent ? window.localStorage : window.sessionStorage;
  const prefix = 'assetmanager:';

  const api = {
    persistent,
    get(key) {
      try { return storage.getItem(prefix + key); } catch (_) { return null; }
    },
    set(key, value) {
      try { storage.setItem(prefix + key, value); } catch (_) {}
    },
    remove(key) {
      try { storage.removeItem(prefix + key); } catch (_) {}
    }
  };
  window.AssetBrowserState = api;

  function tableKey(table, index) {
    return table.dataset.storageKey || table.id || `table-${location.pathname}-${index}`;
  }

  function filterControls(table) {
    return [...table.querySelectorAll('thead input, thead select')].filter(control => {
      const type = (control.type || '').toLowerCase();
      return !['checkbox', 'radio', 'button', 'submit'].includes(type);
    });
  }

  function controlKey(control, index) {
    const cell = control.closest('th');
    return control.name || control.dataset.field || cell?.dataset.field || `filter-${index}`;
  }

  function restoreSort(table, index, force = false) {
    if (!force && table.dataset.browserSortRestored === '1') return;
    if (typeof table.assetApplySort !== 'function') return;

    const key = `${tableKey(table, index)}:sort`;
    let state = null;
    try { state = JSON.parse(api.get(key) || 'null'); } catch (_) {}
    if (state?.field && (state.direction === 'asc' || state.direction === 'desc')) {
      table.assetApplySort(state.field, state.direction, {silent: true});
    } else {
      table.assetUpdateRowNumbers?.();
    }
    table.dataset.browserSortRestored = '1';
  }

  function restoreTable(table, index) {
    if (table.dataset.browserStateReady === '1') return;
    if (table.dataset.serverFilters === '1') {
      table.dataset.browserStateReady = '1';
      restoreSort(table, index);
      return;
    }
    const restoreStarted = performance.now();
    const controls = filterControls(table);
    if (!controls.length) {
      table.dataset.browserStateReady = '1';
      restoreSort(table, index);
      return;
    }

    table.dataset.browserStateReady = '1';
    const key = `${tableKey(table, index)}:filters`;
    let values = {};
    try { values = JSON.parse(api.get(key) || '{}') || {}; } catch (_) {}

    controls.forEach((control, controlIndex) => {
      const field = controlKey(control, controlIndex);
      if (Object.prototype.hasOwnProperty.call(values, field)) {
        // Restore without dispatching one input/change pair per column.
        control.value = values[field];
      }
      const save = () => {
        const current = {};
        filterControls(table).forEach((item, itemIndex) => {
          current[controlKey(item, itemIndex)] = item.value;
        });
        api.set(key, JSON.stringify(current));
      };
      control.addEventListener('input', save);
      control.addEventListener('change', save);
    });

    // One filtering pass after every stored value is in place.
    if (typeof table.assetApplyFilters === 'function') {
      table.assetApplyFilters();
    }
    restoreSort(table, index);
    table.dataset.browserStateRestored = '1';
    window.dispatchEvent(new CustomEvent('asset-table-state-ready', { detail: { table } }));
    const duration = performance.now() - restoreStarted;
    const logger = duration >= 50 ? console.warn : console.debug;
    logger('[AssetManager][Performance]', 'browser-state:restoreTable', {
      dauer_ms: Math.round(duration * 10) / 10,
      filter: controls.length,
      gespeicherte_werte: Object.keys(values).length
    });
  }

  function initializeTables() {
    document.querySelectorAll('table').forEach(restoreTable);
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeTables, { once: true });
  } else {
    initializeTables();
  }

  // Filter controls are added by table-tools.js. Initialize only on its explicit
  // completion event instead of observing every DOM mutation in the document.
  window.addEventListener('asset-table-structure-ready', initializeTables);

  // A programmatic reset does not emit input/change events. Remove the
  // corresponding persisted filter state explicitly so it cannot return after
  // a page refresh.
  window.addEventListener('asset-table-filters-cleared', event => {
    const table = event.detail?.table;
    if (!(table instanceof HTMLTableElement)) return;

    const tables = [...document.querySelectorAll('table')];
    const index = tables.indexOf(table);
    const key = `${tableKey(table, index >= 0 ? index : 0)}:filters`;
    api.remove(key);
  });

  window.addEventListener('asset-table-sort-changed', event => {
    const table = event.detail?.table;
    if (!(table instanceof HTMLTableElement)) return;
    const tables = [...document.querySelectorAll('table')];
    const index = tables.indexOf(table);
    const key = `${tableKey(table, index >= 0 ? index : 0)}:sort`;
    api.set(key, JSON.stringify({
      field: event.detail?.field || '',
      direction: event.detail?.direction || 'asc'
    }));
  });

  window.addEventListener('asset-table-content-reloaded', event => {
    const table = event.detail?.table;
    if (!(table instanceof HTMLTableElement)) return;
    const tables = [...document.querySelectorAll('table')];
    const index = tables.indexOf(table);
    restoreSort(table, index >= 0 ? index : 0, true);
  });

  perf?.end('browser-state:gesamtes Modul');
})();
