• Performs fuzzy search on manga matches.

    Returns top 100 results ordered by relevance score. Uses worker pool for large datasets (100+ items) to prevent UI blocking. Falls back to main thread for small datasets.

    Parameters

    • query: string

      Search query string.

    • matches: MangaMatchResult[]

      Array of manga match results.

    Returns Promise<MangaMatchResult[]>

    Array of matched results with scores.

    export async function fuzzySearchManga(
    query: string,
    matches: MangaMatchResult[],
    ): Promise<MangaMatchResult[]> {
    if (!query.trim()) {
    return matches;
    }

    // Extract text tokens for fuzzy search
    const tokens = parseQuerySyntax(query);
    const textTokens = tokens.filter((t) => t.type === "text");

    if (textTokens.length === 0) {
    // Only field tokens, no fuzzy search needed
    return matches;
    }

    // Combine text tokens for search
    const searchQuery = textTokens.map((t) => t.value).join(" ");

    // Use worker pool for large datasets (100+ items) to prevent UI blocking
    // Small datasets use main thread for faster execution (less overhead)
    if (matches.length >= 100) {
    try {
    const pool = getFuzzySearchWorkerPool();
    await pool.initialize();

    const result = await pool.search(
    matches,
    searchQuery,
    [
    { name: "kenmeiManga.title", weight: 0.5 },
    { name: "selectedMatch.title.romaji", weight: 0.3 },
    { name: "selectedMatch.title.english", weight: 0.3 },
    { name: "selectedMatch.synonyms", weight: 0.1 },
    ],
    { useExtendedSearch: true },
    100,
    );

    return result.results;
    } catch (error) {
    console.warn(
    "[fuzzySearchManga] Worker pool search failed, falling back to main thread:",
    error,
    );
    // Fall through to main thread implementation below
    }
    }

    // Main thread implementation for small datasets
    const fuse = createMangaFuseInstance(matches);
    const results = fuse.search(searchQuery);

    // Return top 100 results
    return results.slice(0, 100).map((result) => result.item);
    }