• Prepare all entries to sync from matched manga, applying configuration rules. Filters to matched/manual entries and respects preserveCompletedStatus setting.

    Parameters

    • mangaMatches: MangaMatchResult[]

      Array of manga match results.

    • userLibrary: UserMediaList

      User's existing AniList library indexed by media ID.

    • syncConfig: SyncConfig

      Sync configuration with priority settings.

    Returns AniListMediaEntry[]

    Array of AniList media entries ready for synchronization.

    export function prepareAllEntriesToSync(
    mangaMatches: MangaMatchResult[],
    userLibrary: UserMediaList,
    syncConfig: SyncConfig,
    ): AniListMediaEntry[] {
    return mangaMatches
    .filter((match) => match.status === "matched" || match.status === "manual")
    .filter((match) => match.selectedMatch !== undefined)
    .map((match) => {
    // Get Kenmei data
    const kenmei = match.kenmeiManga;
    const anilist = match.selectedMatch!;
    const userEntry = userLibrary[anilist.id];
    if (
    userEntry?.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ) {
    return null;
    }

    const computeCalculatedStatus = (): MediaListStatus => {
    // Reuse existing getEffectiveStatus logic which already handles auto-pause checks
    const kenmeiStatusSnapshot: KenmeiMangaData = {
    status: kenmei.status,
    updatedAt: kenmei.updatedAt,
    lastReadAt: kenmei.lastReadAt,
    title: kenmei.title,
    chaptersRead: kenmei.chaptersRead,
    score: kenmei.score,
    };
    return getEffectiveStatus(kenmeiStatusSnapshot, syncConfig);
    };
    const calculatedStatus = computeCalculatedStatus();
    let shouldSetPrivate: boolean;
    if (userEntry) {
    if (syncConfig.setPrivate) {
    shouldSetPrivate = true;
    } else {
    shouldSetPrivate = userEntry.private || false;
    }
    } else {
    shouldSetPrivate = syncConfig.setPrivate;
    }
    const entry: AniListMediaEntry = {
    mediaId: anilist.id,
    status:
    syncConfig.prioritizeAniListStatus && userEntry?.status
    ? userEntry.status
    : calculatedStatus,
    progress: (() => {
    if (
    syncConfig.prioritizeAniListProgress &&
    userEntry?.progress &&
    userEntry.progress > 0
    ) {
    const kenmeiProgress = kenmei.chaptersRead || 0;
    return Math.max(userEntry.progress, kenmeiProgress);
    }
    return kenmei.chaptersRead || 0;
    })(),
    private: shouldSetPrivate,
    score: (() => {
    if (
    userEntry &&
    syncConfig.prioritizeAniListScore &&
    userEntry.score > 0
    ) {
    return userEntry.score;
    }
    return typeof kenmei.score === "number" ? kenmei.score : 0;
    })(),
    previousValues: userEntry
    ? {
    status: userEntry.status,
    progress:
    typeof userEntry.progress === "number" ? userEntry.progress : 0,
    score: typeof userEntry.score === "number" ? userEntry.score : 0,
    private: userEntry.private || false,
    }
    : null,
    title: anilist.title.romaji || kenmei.title,
    coverImage: anilist.coverImage?.large || anilist.coverImage?.medium,
    };
    entry.private ??= syncConfig.setPrivate || false;
    return entry;
    })
    .filter((entry): entry is AniListMediaEntry => entry !== null);
    }