• Finds the best matching AniList entries for a Kenmei manga with automatic status determination.

    Scores all candidates and returns ranked results (by confidence descending). Automatically categorizes results:

    • "matched": Exact match found OR high confidence (≥threshold) with ≥20 point lead
    • "pending": Multiple close candidates, low confidence, or ambiguous results

    Returns up to maxMatches candidates with confidence > 0.

    Parameters

    Returns MangaMatchResult

    Match result with ranked candidates, status, and selected match.

    export function findBestMatches(
    kenmeiManga: KenmeiManga,
    anilistMangaList: AniListManga[],
    config: Partial<MatchEngineConfig> = {},
    ): MangaMatchResult {
    const matchConfig = { ...DEFAULT_MATCH_CONFIG, ...config };

    // Calculate match scores for each AniList manga and sort descending
    const matchResults = anilistMangaList
    .map((manga) => {
    const matchScore = scoreMatch(kenmeiManga, manga, matchConfig);
    const confidence = calculateConfidence(kenmeiManga.title, manga);
    return {
    manga,
    confidence,
    isExactMatch: matchScore.isExactMatch,
    matchedField: matchScore.matchedField,
    } as const;
    })
    .sort((a, b) => b.confidence - a.confidence);

    // Take only the top matches and exclude zero-confidence entries
    const topMatches = matchResults
    .slice(0, matchConfig.maxMatches)
    .filter((m) => m.confidence > 0);

    if (topMatches.length === 0) {
    return {
    kenmeiManga,
    anilistMatches: [],
    status: "pending",
    selectedMatch: undefined,
    matchDate: new Date().toISOString(),
    };
    }

    if (topMatches[0].isExactMatch) {
    return {
    kenmeiManga,
    anilistMatches: topMatches.map(({ manga, confidence }) => ({
    id: manga.id,
    manga,
    confidence,
    })),
    status: "matched",
    selectedMatch: topMatches[0].manga,
    matchDate: new Date().toISOString(),
    };
    }

    const hasHighConfidence =
    topMatches[0].confidence >= matchConfig.confidenceThreshold &&
    (topMatches.length === 1 ||
    topMatches[0].confidence - topMatches[1].confidence > 20);

    if (hasHighConfidence) {
    return {
    kenmeiManga,
    anilistMatches: topMatches.map(({ manga, confidence }) => ({
    id: manga.id,
    manga,
    confidence,
    })),
    status: "matched",
    selectedMatch: topMatches[0].manga,
    matchDate: new Date().toISOString(),
    };
    }

    // Multiple potential matches or low confidence => pending
    return {
    kenmeiManga,
    anilistMatches: topMatches.map(({ manga, confidence }) => ({
    id: manga.id,
    manga,
    confidence,
    })),
    status: "pending",
    selectedMatch: undefined,
    matchDate: new Date().toISOString(),
    };
    }