function controlState(state, key) {
  state.tableFilters ||= {};
  return state.tableFilters[key] ||= { query: '', status: 'all', filters: {} };
}

function searchable(value) {
  if (value == null) return '';
  if (Array.isArray(value)) return value.map(searchable).join(' ');
  if (typeof value === 'object') return Object.values(value).map(searchable).join(' ');
  return String(value);
}

function statusTokens(item) {
  const tokens = [item?.status, item?.paymentStatus];
  if (typeof item?.active === 'boolean') tokens.push(item.active ? 'active approved' : 'inactive disabled closed');
  if (typeof item?.published === 'boolean') tokens.push(item.published ? 'published visible' : 'draft hidden');
  if (typeof item?.qualified === 'boolean') tokens.push(item.qualified ? 'qualified' : 'unqualified');
  if (typeof item?.confirmed === 'boolean') tokens.push(item.confirmed ? (item.eligible ? 'confirmed eligible' : 'confirmed ineligible') : 'unconfirmed');
  return tokens.filter(Boolean).join(' ').toLowerCase();
}

export function filterTableItems(state, items, key) {
  const control = controlState(state, key);
  const query = String(control.query || '').trim().toLocaleLowerCase('zh-CN');
  const status = String(control.status || 'all').toLowerCase();
  const filters = Object.values(control.filters || {}).filter(Boolean).map(value => String(value).toLocaleLowerCase('zh-CN'));
  return (items || []).filter(item => {
    const haystack = searchable(item).toLocaleLowerCase('zh-CN');
    if (query && !query.split(/\s+/).every(word => haystack.includes(word))) return false;
    if (status !== 'all' && !statusTokens(item).split(/\s+/).includes(status)) return false;
    return filters.every(value => haystack.includes(value));
  });
}

export function setTableControl(state, key, patch) {
  const current = controlState(state, key);
  Object.assign(current, patch);
  if (patch.filters) current.filters = { ...(current.filters || {}), ...patch.filters };
  if (state.tablePages?.[key]) state.tablePages[key].page = 1;
}

export function getTableControl(state, key) {
  return controlState(state, key);
}
