export type Tab =
  | 'library'
  | 'servers'
  | 'audio'
  | 'lyrics'
  | 'appearance'
  | 'themes'
  | 'personalisation'
  | 'integrations'
  | 'input'
  | 'storage'
  | 'system'
  | 'users';

// Legacy Tab-IDs die via Route-State oder persisted State noch aufschlagen koennen
// auf die neue Struktur mappen. Gibt es keinen Match, faellt die Settings-Page
// einfach auf 'library' zurueck.
const LEGACY_TAB_ALIAS: Record<string, Tab> = {
  general: 'library',
  server: 'servers',
};

export function resolveTab(input: string | undefined | null): Tab {
  if (!input) return 'servers';
  const aliased = LEGACY_TAB_ALIAS[input];
  if (aliased) return aliased;
  const known: Tab[] = ['library', 'servers', 'audio', 'lyrics', 'appearance', 'themes', 'personalisation', 'integrations', 'input', 'storage', 'system', 'users'];
  return (known as string[]).includes(input) ? (input as Tab) : 'servers';
}

// Statischer Suchindex ueber alle Sub-Sections aller Tabs. Mitpflegen, wenn eine
// neue SettingsSubSection hinzukommt — sonst taucht sie nicht in der Suche auf.
export type SearchIndexEntry = { tab: Tab; titleKey: string; keywords?: string; focusTitleKey?: string };

export const SETTINGS_INDEX: SearchIndexEntry[] = [
  { tab: 'audio',          titleKey: 'settings.audioOutputDevice',        keywords: 'output device speakers headphones alsa wasapi coreaudio' },
  { tab: 'audio',          titleKey: 'settings.hiResTitle',               keywords: 'hi-res hires resampling bit depth sample rate dsd 24bit crossfade autodj blend 44 88 96' },
  { tab: 'audio',          titleKey: 'settings.eqTitle',                  keywords: 'equalizer eq bass treble autoeq filter pre-gain' },
  { tab: 'audio',          titleKey: 'settings.playbackRateTitle',        keywords: 'speed playback rate tempo pitch varispeed preserve corrected time stretch' },
  { tab: 'audio',          titleKey: 'settings.normalization',            keywords: 'normalization normalisation loudness volume leveling level replaygain replay gain lufs pre-gain' },
  { tab: 'audio',          titleKey: 'settings.transitionsTitle',         keywords: 'track transitions crossfade autodj auto dj smart crossfade gapless blend fade trim silence' },
  { tab: 'lyrics',         titleKey: 'settings.lyricsSourcesTitle',       keywords: 'lyrics sources providers lrclib netease server youlyplus karaoke standard static' },
  { tab: 'lyrics',         titleKey: 'settings.sidebarLyricsStyle',       keywords: 'lyrics scroll style classic apple music' },
  { tab: 'integrations',   titleKey: 'musicNetwork.title',                keywords: 'last.fm lastfm libre.fm rocksky listenbrainz maloja scrobble scrobbling music network' },
  { tab: 'integrations',   titleKey: 'settings.discordRichPresence',      keywords: 'discord rich presence rpc' },
  { tab: 'integrations',   titleKey: 'settings.enableBandsintown',        keywords: 'bandsintown concerts tours events' },
  { tab: 'integrations',   titleKey: 'settings.nowPlayingEnabled',        keywords: 'now playing share dropdown presence' },
  { tab: 'personalisation',titleKey: 'settings.sidebarTitle',             keywords: 'sidebar nav navigation items reorder customize' },
  { tab: 'personalisation',titleKey: 'settings.artistLayoutTitle',        keywords: 'artist page layout sections order' },
  { tab: 'personalisation',titleKey: 'settings.homeCustomizerTitle',      keywords: 'mainstage home page customize sections' },
  { tab: 'personalisation',titleKey: 'settings.queueSettingsTitle',       keywords: 'queue settings display mode list playlist timeline toolbar buttons reorder customize shuffle save load behaviour behavior preserve play next order' },
  { tab: 'personalisation',titleKey: 'settings.playlistLayoutTitle',     keywords: 'playlist page layout add songs import csv download zip cache offline suggestions controls hide show' },
  { tab: 'personalisation',titleKey: 'settings.playerBarTitle',          keywords: 'player bar playback favorites stars rating lastfm love equalizer mini player controls hide show' },
  { tab: 'appearance',     titleKey: 'settings.libraryGridMaxColumnsTitle', keywords: 'grid columns album artist playlist cards layout appearance performance scroll paint' },
  { tab: 'servers',        titleKey: 'settings.servers',                  keywords: 'local library index sync resync verify integrity offline delta background sqlite search' },
  { tab: 'servers',        titleKey: 'settings.audiomuseTitle',           keywords: 'audiomuse audio muse navidrome plugin instant mix similar songs lucky mix' },
  { tab: 'library',        titleKey: 'settings.analyticsStrategyTitle',   keywords: 'analytics strategy analysis bpm enrichment waveform lazy advanced library backfill' },
  { tab: 'library',        titleKey: 'settings.randomMixTitle',           keywords: 'random mix blacklist genre keywords filter audiobook' },
  { tab: 'library',        titleKey: 'settings.ratingsSectionTitle',      keywords: 'ratings stars skip threshold manual' },
  { tab: 'storage',        titleKey: 'settings.coverCacheStrategyTitle', keywords: 'cover art cache webp aggressive lazy disk per server image idb preview limit clear' },
  { tab: 'storage',        titleKey: 'settings.mediaDirTitle',            keywords: 'media folder offline library cache directory local playback' },
  { tab: 'storage',        titleKey: 'settings.nextTrackBufferingTitle',  keywords: 'next track buffering hot cache streaming' },
  { tab: 'storage',        titleKey: 'settings.downloadsTitle',           keywords: 'downloads zip export archive folder' },
  { tab: 'themes',         titleKey: 'settings.themesYourThemesTitle',    keywords: 'theme color palette dark light install uninstall apply your' },
  { tab: 'themes',         titleKey: 'settings.themeSchedulerTitle',      keywords: 'theme scheduler auto time dark mode sunset' },
  { tab: 'themes',         titleKey: 'settings.themeStoreTitle',          keywords: 'theme store community download install browse marketplace' },
  { tab: 'appearance',     titleKey: 'settings.visualOptionsTitle',       keywords: 'visual options animations effects titlebar mini player' },
  { tab: 'appearance',     titleKey: 'settings.uiScaleTitle',             keywords: 'ui scale zoom dpi size' },
  { tab: 'appearance',     titleKey: 'settings.font',                     keywords: 'font typography typeface' },
  { tab: 'appearance',     titleKey: 'settings.seekbarStyle',             keywords: 'seekbar progress bar waveform reduced animations performance gpu fps low-end framerate cap' },
  { tab: 'input',          titleKey: 'settings.inputKeybindingsTitle',    keywords: 'keybindings shortcuts hotkeys keyboard' },
  { tab: 'input',          titleKey: 'settings.globalShortcutsTitle',     keywords: 'global shortcuts hotkeys system-wide media keys' },
  { tab: 'system',         titleKey: 'settings.language',                 keywords: 'language locale translation i18n' },
  { tab: 'system',         titleKey: 'settings.behavior',                 keywords: 'behavior tray minimize close start minimized launch hidden smooth scroll linux' },
  { tab: 'system',         titleKey: 'settings.backupTitle',              keywords: 'backup export import settings restore' },
  { tab: 'system',         titleKey: 'settings.loggingTitle',             keywords: 'log logs diagnostic debug verbose' },
  { tab: 'system',         titleKey: 'settings.aboutTitle',               keywords: 'about version update changelog release notes' },
  { tab: 'system',         titleKey: 'settings.aboutContributorsLabel',   keywords: 'contributors credits maintainers' },
  { tab: 'system',         titleKey: 'licenses.title',                    keywords: 'licenses license open source attribution copyright third party dependencies oss' },
];

// Substring-first, compact fuzzy fallback (query chars in order within a
// short span). Returns 0 = no match. Higher = better.
export function matchScore(haystack: string, needle: string): number {
  if (!needle) return 0;
  const h = haystack.toLowerCase();
  const n = needle.toLowerCase();
  const idx = h.indexOf(n);
  if (idx >= 0) return 1000 - Math.min(999, idx);
  // Repeated single-char queries ("aaaaaaa") must not match via sparse fuzzy hits.
  if (n.length >= 4 && /^(.)\1+$/.test(n)) return 0;
  let hi = 0;
  let start = -1;
  for (const ch of n) {
    const j = h.indexOf(ch, hi);
    if (j < 0) return 0;
    if (start < 0) start = j;
    hi = j + 1;
  }
  const span = hi - start;
  if (span > n.length * 2) return 0;
  if (n.length >= 4 && span > n.length + 3) return 0;
  return Math.max(1, 100 - Math.min(99, span - n.length));
}
