• Sync page component for the Kenmei to AniList sync tool.

    Handles synchronization preview, configuration, execution, and results display for the user.

    Returns Element

    export function SyncPage() {
    const navigate = useNavigate();
    const { authState } = useAuth();
    const token = authState.accessToken || "";
    const [state, actions] = useSynchronization();
    const [viewMode, setViewMode] = useState<"preview" | "sync" | "results">(
    "preview",
    );
    const { rateLimitState, setRateLimit } = useRateLimit();

    // Animation configs - remove unused variants
    const pageVariants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1, transition: { duration: 0.4 } },
    exit: { opacity: 0, transition: { duration: 0.2 } },
    };

    const cardVariants = {
    hidden: { opacity: 0, y: 20 },
    visible: {
    opacity: 1,
    y: 0,
    transition: {
    duration: 0.4,
    delay: 0.1,
    },
    },
    };

    const staggerContainerVariants = {
    hidden: { opacity: 0 },
    visible: {
    opacity: 1,
    transition: {
    staggerChildren: 0.1,
    delayChildren: 0.2,
    },
    },
    };

    // Add a specific transition for view modes to prevent warping
    const viewModeTransition = {
    type: "tween",
    ease: "easeInOut",
    duration: 0.2,
    };

    // Create variants that only animate opacity, not size or position
    const fadeVariants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1 },
    exit: { opacity: 0 },
    };

    // Authentication and validation states
    const [authError, setAuthError] = useState(false);
    const [matchDataError, setMatchDataError] = useState(false);
    const [validMatchesError, setValidMatchesError] = useState(false);

    // Authentication and data validation check
    useEffect(() => {
    // Check if user is authenticated
    if (!authState.isAuthenticated || !token) {
    console.log("User not authenticated, showing auth error");
    setAuthError(true);
    return;
    } else {
    setAuthError(false);
    }

    // Check if there are match results to sync
    const savedResults = getSavedMatchResults();
    if (
    !savedResults ||
    !Array.isArray(savedResults) ||
    savedResults.length === 0
    ) {
    console.log("No match results found, showing match data error");
    setMatchDataError(true);
    return;
    } else {
    setMatchDataError(false);
    }

    // Validate that there are actual matches (not just skipped entries)
    const validMatches = savedResults.filter(
    (match) => match.status === "matched" || match.status === "manual",
    );

    if (validMatches.length === 0) {
    console.log("No valid matches found, showing valid matches error");
    setValidMatchesError(true);
    return;
    } else {
    setValidMatchesError(false);
    }

    console.log(
    `Found ${validMatches.length} valid matches for synchronization`,
    );
    }, [authState.isAuthenticated, token]);

    // Sync configuration options
    const [syncConfig, setSyncConfig] = useState<SyncConfig>(getSyncConfig());
    // Track if we're using a custom threshold
    const [useCustomThreshold, setUseCustomThreshold] = useState<boolean>(
    ![1, 7, 14, 30, 60, 90, 180, 365].includes(syncConfig.autoPauseThreshold),
    );

    const getEffectiveStatus = (kenmei: {
    status: string;
    updated_at: string;
    last_read_at?: string;
    }): MediaListStatus => {
    // Check if manga should be auto-paused due to inactivity
    const lastActivity = kenmei.last_read_at || kenmei.updated_at;
    if (
    syncConfig.autoPauseInactive &&
    kenmei.status.toLowerCase() !== "completed" &&
    kenmei.status.toLowerCase() !== "dropped" &&
    lastActivity
    ) {
    // Calculate how many days since the last activity
    const lastUpdated = new Date(lastActivity);
    const daysSinceUpdate = Math.floor(
    (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24),
    );

    // If using a custom threshold
    if ((syncConfig.autoPauseThreshold as unknown as string) === "custom") {
    const customThreshold = syncConfig.customAutoPauseThreshold || 30;
    if (daysSinceUpdate >= customThreshold) {
    return "PAUSED";
    }
    }
    // Using a predefined threshold (explicitly cast to number for type safety)
    else if (daysSinceUpdate >= (syncConfig.autoPauseThreshold as number)) {
    return "PAUSED";
    }
    }

    // Otherwise use the normal status mapping
    // Use type assertion for safety
    const status = kenmei.status as KenmeiStatus;
    return STATUS_MAPPING[status];
    };

    // Toggle handler for sync options
    const handleToggleOption = (option: keyof SyncConfig) => {
    setSyncConfig((prev) => {
    const newConfig = {
    ...prev,
    [option]: !prev[option],
    };

    // Save the updated config to storage
    saveSyncConfig(newConfig);

    return newConfig;
    });
    };

    // View mode for displaying manga entries
    const [displayMode, setDisplayMode] = useState<"cards" | "compact">("cards");

    // State to hold manga matches
    const [mangaMatches, setMangaMatches] = useState<MangaMatchResult[]>([]);

    // Pagination and loading state
    const [visibleItems, setVisibleItems] = useState(20);
    const [isLoadingMore, setIsLoadingMore] = useState(false);
    // State to hold user's AniList library
    const [userLibrary, setUserLibrary] = useState<UserMediaList>({});
    const [libraryLoading, setLibraryLoading] = useState(false);
    const [libraryError, setLibraryError] = useState<string | null>(null);
    const [retryCount, setRetryCount] = useState(0);
    const maxRetries = 3;

    // Sorting and filtering options
    const [sortOption, setSortOption] = useState<{
    field: "title" | "status" | "progress" | "score" | "changes";
    direction: "asc" | "desc";
    }>({ field: "title", direction: "asc" });

    const [filters, setFilters] = useState({
    status: "all", // 'all', 'reading', 'completed', 'planned', 'paused', 'dropped'
    changes: "all", // 'all', 'with-changes', 'no-changes'
    library: "all", // 'all', 'new', 'existing'
    });

    // Load manga matches from the app's storage system
    useEffect(() => {
    const savedResults = getSavedMatchResults();
    if (savedResults && Array.isArray(savedResults)) {
    console.log(`Loaded ${savedResults.length} match results from storage`);
    setMangaMatches(savedResults as MangaMatchResult[]);
    } else {
    console.error("No match results found in storage");
    }
    }, []);

    // Fetch the user's AniList library for comparison
    useEffect(() => {
    if (token && mangaMatches.length > 0) {
    setLibraryLoading(true);
    setLibraryError(null);

    const controller = new AbortController();

    const fetchLibrary = (attempt = 0) => {
    console.log(
    `Fetching AniList library (attempt ${attempt + 1}/${maxRetries + 1})`,
    );
    setRetryCount(attempt);

    getUserMangaList(token, controller.signal)
    .then((library) => {
    console.log(
    `Loaded ${Object.keys(library).length} entries from user's AniList library`,
    );
    setUserLibrary(library);
    setLibraryLoading(false);
    setLibraryError(null);
    setRetryCount(0);
    })
    .catch((error) => {
    if (error.name === "AbortError") return;

    console.error("Failed to load user library:", error);
    console.log(
    "Error object structure:",
    JSON.stringify(error, null, 2),
    );

    // Check for rate limiting - with our new client updates, this should be more reliable
    if (error.isRateLimited || error.status === 429) {
    console.warn("📛 DETECTED RATE LIMIT in SyncPage:", {
    isRateLimited: error.isRateLimited,
    status: error.status,
    retryAfter: error.retryAfter,
    });

    const retryDelay = error.retryAfter ? error.retryAfter : 60;

    // Update the global rate limit state
    setRateLimit(
    true,
    retryDelay,
    "AniList API rate limit reached. Waiting to retry...",
    );

    // Set library loading state
    setLibraryLoading(false);
    setLibraryError(
    "AniList API rate limit reached. Waiting to retry...",
    );

    // Set a timer to retry after the delay
    const timer = setTimeout(() => {
    if (!controller.signal.aborted) {
    console.log("Rate limit timeout complete, retrying...");
    setLibraryLoading(true);
    setLibraryError(null);
    fetchLibrary(0); // Reset retry count for rate limits
    }
    }, retryDelay * 1000);

    return () => clearTimeout(timer);
    }

    // Check for server error (5xx) or network error
    const isServerError =
    error.message?.includes("500") ||
    error.message?.includes("502") ||
    error.message?.includes("503") ||
    error.message?.includes("504") ||
    error.message?.toLowerCase().includes("network error");

    if (isServerError && attempt < maxRetries) {
    // Exponential backoff for retries (1s, 2s, 4s)
    const backoffDelay = Math.pow(2, attempt) * 1000;
    setLibraryError(
    `AniList server error. Retrying in ${backoffDelay / 1000} seconds (${attempt + 1}/${maxRetries})...`,
    );

    // Set a timer to retry
    const timer = setTimeout(() => {
    if (!controller.signal.aborted) {
    fetchLibrary(attempt + 1);
    }
    }, backoffDelay);

    return () => clearTimeout(timer);
    }

    // If we get here, either it's not a server error or we've exceeded retry attempts
    setLibraryError(
    error.message ||
    "Failed to load your AniList library. Synchronization can still proceed, but comparison data will not be shown.",
    );
    setUserLibrary({});
    setLibraryLoading(false);
    });
    };

    fetchLibrary(0);

    return () => controller.abort();
    }
    }, [token, mangaMatches, maxRetries, setRateLimit]);

    // Reset visible items when changing display mode
    useEffect(() => {
    setVisibleItems(20);
    }, [displayMode]);

    // Apply filters to manga matches
    const filteredMangaMatches = useMemo(() => {
    return mangaMatches
    .filter(
    (match) => match.status === "matched" || match.status === "manual",
    )
    .filter((match) => match.selectedMatch !== undefined)
    .filter((match) => {
    // Status filter
    if (filters.status !== "all") {
    const kenmeiStatus = match.kenmeiManga.status.toLowerCase();

    if (filters.status === "reading" && kenmeiStatus !== "reading")
    return false;
    if (filters.status === "completed" && kenmeiStatus !== "completed")
    return false;
    if (filters.status === "planned" && kenmeiStatus !== "plan_to_read")
    return false;
    if (filters.status === "paused" && kenmeiStatus !== "on_hold")
    return false;
    if (filters.status === "dropped" && kenmeiStatus !== "dropped")
    return false;
    }

    // Changes filter
    if (filters.changes !== "all") {
    const anilist = match.selectedMatch!;
    const kenmei = match.kenmeiManga;
    const userEntry = userLibrary[anilist.id];

    // Calculate if any changes will be made
    const isCompleted =
    userEntry &&
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus;

    // If completed and we're preserving completed status, no changes will be made
    if (isCompleted) {
    if (filters.changes === "with-changes") return false;
    } else {
    const statusWillChange = userEntry
    ? syncConfig.prioritizeAniListStatus
    ? false
    : getEffectiveStatus(kenmei) !== userEntry.status
    : true;

    const progressWillChange = userEntry
    ? syncConfig.prioritizeAniListProgress
    ? // Will only change if Kenmei has more chapters read than AniList
    (kenmei.chapters_read || 0) > (userEntry.progress || 0)
    : (kenmei.chapters_read || 0) !== (userEntry.progress || 0)
    : true;

    const anilistScore = userEntry ? Number(userEntry.score || 0) : 0;
    const kenmeiScore = Number(kenmei.score || 0);

    const scoreWillChange = userEntry
    ? userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ? false
    : syncConfig.prioritizeAniListScore && anilistScore > 0
    ? false
    : kenmeiScore > 0 &&
    (anilistScore === 0 ||
    Math.abs(kenmeiScore - anilistScore) >= 0.5)
    : kenmeiScore > 0;

    const hasChanges =
    statusWillChange ||
    progressWillChange ||
    scoreWillChange ||
    (syncConfig.setPrivate && userEntry && !userEntry.private);

    if (filters.changes === "with-changes" && !hasChanges) return false;
    if (filters.changes === "no-changes" && hasChanges) return false;
    }
    }

    // Library filter
    if (filters.library !== "all") {
    const anilist = match.selectedMatch!;
    const isNewEntry = !userLibrary[anilist.id];

    if (filters.library === "new" && !isNewEntry) return false;
    if (filters.library === "existing" && isNewEntry) return false;
    }

    return true;
    });
    }, [mangaMatches, filters, userLibrary, syncConfig]);

    // Apply sorting to filtered manga matches
    const sortedMangaMatches = useMemo(() => {
    return [...filteredMangaMatches].sort((a, b) => {
    const anilistA = a.selectedMatch!;
    const anilistB = b.selectedMatch!;
    const kenmeiA = a.kenmeiManga;
    const kenmeiB = b.kenmeiManga;

    // Calculate changes for sorting by changes
    const getChangeCount = (match: MangaMatchResult) => {
    const anilist = match.selectedMatch!;
    const kenmei = match.kenmeiManga;
    const userEntry = userLibrary[anilist.id];
    const isCompleted =
    userEntry &&
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus;

    if (isCompleted) return 0;
    if (!userEntry) return 3; // New entry, all fields will change

    const statusWillChange =
    !syncConfig.prioritizeAniListStatus &&
    getEffectiveStatus(kenmei) !== userEntry.status;

    const progressWillChange = syncConfig.prioritizeAniListProgress
    ? (kenmei.chapters_read || 0) > (userEntry.progress || 0)
    : (kenmei.chapters_read || 0) !== (userEntry.progress || 0);

    const anilistScore = Number(userEntry.score);
    const kenmeiScore = Number(kenmei.score || 0);

    const scoreWillChange =
    !syncConfig.prioritizeAniListScore &&
    kenmei.score > 0 &&
    (anilistScore === 0 || Math.abs(kenmeiScore - anilistScore) >= 0.5);

    // Check if privacy will change
    const privacyWillChange = syncConfig.setPrivate && !userEntry.private;

    return (
    (statusWillChange ? 1 : 0) +
    (progressWillChange ? 1 : 0) +
    (scoreWillChange ? 1 : 0) +
    (privacyWillChange ? 1 : 0)
    );
    };

    // Sort based on the selected field
    let comparison = 0;

    switch (sortOption.field) {
    case "title":
    comparison = (anilistA.title.romaji || kenmeiA.title).localeCompare(
    anilistB.title.romaji || kenmeiB.title,
    );
    break;
    case "status":
    comparison = kenmeiA.status.localeCompare(kenmeiB.status);
    break;
    case "progress":
    comparison =
    (kenmeiA.chapters_read || 0) - (kenmeiB.chapters_read || 0);
    break;
    case "score":
    comparison = (kenmeiA.score || 0) - (kenmeiB.score || 0);
    break;
    case "changes":
    comparison = getChangeCount(b) - getChangeCount(a);
    break;
    default:
    comparison = 0;
    }

    // Apply sort direction
    return sortOption.direction === "asc" ? comparison : -comparison;
    });
    }, [filteredMangaMatches, sortOption, userLibrary, syncConfig]);

    // Compute all entries to sync (unfiltered, all with changes)
    const allEntriesToSync = useMemo(() => {
    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 &&
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ) {
    return null;
    }
    let calculatedStatus: MediaListStatus;
    if (
    syncConfig.autoPauseInactive &&
    kenmei.status.toLowerCase() !== "completed" &&
    kenmei.status.toLowerCase() !== "dropped" &&
    kenmei.updated_at
    ) {
    const lastUpdated = new Date(kenmei.updated_at);
    const daysSinceUpdate = Math.floor(
    (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24),
    );
    if (daysSinceUpdate >= syncConfig.autoPauseThreshold) {
    calculatedStatus = "PAUSED";
    } else {
    calculatedStatus = STATUS_MAPPING[kenmei.status];
    }
    } else {
    calculatedStatus = STATUS_MAPPING[kenmei.status];
    }
    const privateStatus = userEntry
    ? syncConfig.setPrivate
    ? true
    : userEntry.private || false
    : syncConfig.setPrivate;
    const entry: AniListMediaEntry = {
    mediaId: anilist.id,
    status:
    syncConfig.prioritizeAniListStatus && userEntry?.status
    ? (userEntry.status as MediaListStatus)
    : calculatedStatus,
    progress:
    syncConfig.prioritizeAniListProgress &&
    userEntry?.progress &&
    userEntry.progress > 0
    ? userEntry.progress > (kenmei.chapters_read || 0)
    ? userEntry.progress
    : kenmei.chapters_read || 0
    : kenmei.chapters_read || 0,
    private: privateStatus,
    score:
    userEntry &&
    syncConfig.prioritizeAniListScore &&
    userEntry.score > 0
    ? userEntry.score
    : 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,
    };
    if (entry.private === undefined) {
    entry.private = syncConfig.setPrivate || false;
    }
    return entry;
    })
    .filter((entry) => entry !== null) as AniListMediaEntry[];
    }, [mangaMatches, userLibrary, syncConfig]);

    // Only sync entries with actual changes
    const hasChanges = (entry: AniListMediaEntry) => {
    // New entry: not in userLibrary
    if (!entry.previousValues) return true;

    // Completed and preserve setting: skip
    if (
    entry.previousValues.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ) {
    return false;
    }

    // Status change
    const statusWillChange = syncConfig.prioritizeAniListStatus
    ? false
    : entry.status !== entry.previousValues.status;

    // Progress change
    const progressWillChange = syncConfig.prioritizeAniListProgress
    ? entry.progress > entry.previousValues.progress
    : entry.progress !== entry.previousValues.progress;

    // Score change
    const anilistScore = Number(entry.previousValues.score || 0);
    const kenmeiScore = Number(entry.score || 0);
    const scoreWillChange =
    entry.previousValues.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ? false
    : syncConfig.prioritizeAniListScore && anilistScore > 0
    ? false
    : kenmeiScore > 0 &&
    (anilistScore === 0 || Math.abs(kenmeiScore - anilistScore) >= 0.5);

    // Privacy change
    const privacyWillChange =
    syncConfig.setPrivate && !entry.previousValues.private;

    return (
    statusWillChange ||
    progressWillChange ||
    scoreWillChange ||
    privacyWillChange
    );
    };
    const entriesWithChanges = useMemo(
    () => allEntriesToSync.filter(hasChanges),
    [allEntriesToSync],
    );

    // Modify handleStartSync to only change the view, not start synchronization
    const handleStartSync = () => {
    if (entriesWithChanges.length === 0) {
    return;
    }
    setViewMode("sync");
    };

    // Handle sync completion
    const handleSyncComplete = () => {
    setViewMode("results");
    };

    // Handle sync cancellation
    const [wasCancelled, setWasCancelled] = useState(false);
    const handleCancel = () => {
    if (viewMode === "sync") {
    // If sync has not started, go back to preview
    if (!state.isActive && !state.report) {
    setViewMode("preview");
    return;
    }
    actions.cancelSync();
    setWasCancelled(true);
    setViewMode("results");
    return;
    }
    // Navigate back to the matching page
    navigate({ to: "/review" });
    };

    // Handle final completion (after viewing results)
    const handleGoHome = () => {
    actions.reset();
    setWasCancelled(false);
    navigate({ to: "/" });
    };
    // Helper to refresh AniList library
    const refreshUserLibrary = () => {
    setLibraryLoading(true);
    setLibraryError(null);
    setRetryCount(0);
    setRateLimit(false, undefined, undefined);

    const controller = new AbortController();

    getUserMangaList(token, controller.signal)
    .then((library) => {
    setUserLibrary(library);
    setLibraryLoading(false);
    })
    .catch((error) => {
    if (error.name !== "AbortError") {
    if (error.isRateLimited || error.status === 429) {
    const retryDelay = error.retryAfter ? error.retryAfter : 60;
    setRateLimit(
    true,
    retryDelay,
    "AniList API rate limit reached. Waiting to retry...",
    );
    } else {
    setLibraryError(
    error.message ||
    "Failed to load your AniList library. Synchronization can still proceed without comparison data.",
    );
    }
    setUserLibrary({});
    setLibraryLoading(false);
    }
    });
    };

    const handleBackToReview = () => {
    actions.reset();
    setWasCancelled(false);
    refreshUserLibrary();
    setViewMode("preview");
    };

    // If any error condition is true, show the appropriate error message
    if (authError || matchDataError || validMatchesError) {
    return (
    <div className="container py-6">
    <motion.div
    initial={{ opacity: 0, scale: 0.95 }}
    animate={{ opacity: 1, scale: 1 }}
    transition={{ delay: 0.25, duration: 0.3 }}
    >
    <Card
    className={`mx-auto w-full max-w-md overflow-hidden text-center ${authError ? "border-amber-200 bg-amber-50/30 dark:border-amber-800/30 dark:bg-amber-900/10" : ""}`}
    >
    <CardContent className="pt-6 pb-4">
    <div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-amber-100 dark:bg-amber-900/30">
    <AlertCircle className="h-6 w-6 text-amber-600 dark:text-amber-400" />
    </div>

    {authError && (
    <>
    <h3 className="text-lg font-medium">
    Authentication Required
    </h3>
    <p className="mt-2 text-sm text-slate-600 dark:text-slate-400">
    You need to be authenticated with AniList to synchronize
    your manga.
    </p>
    <Button
    onClick={() => navigate({ to: "/settings" })}
    className="mt-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700"
    >
    Go to Settings
    </Button>
    </>
    )}

    {matchDataError && !authError && (
    <>
    <h3 className="text-lg font-medium">Missing Match Data</h3>
    <p className="mt-2 text-sm text-slate-600 dark:text-slate-400">
    No matched manga found. You need to match your manga with
    AniList entries first.
    </p>
    <Button
    onClick={() => navigate({ to: "/review" })}
    className="mt-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700"
    >
    Go to Matching Page
    </Button>
    </>
    )}

    {validMatchesError && !authError && !matchDataError && (
    <>
    <h3 className="text-lg font-medium">No Valid Matches</h3>
    <p className="mt-2 text-sm text-slate-600 dark:text-slate-400">
    No approved matches found. You need to review and accept
    manga matches before synchronizing.
    </p>
    <Button
    onClick={() => navigate({ to: "/review" })}
    className="mt-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700"
    >
    Review Matches
    </Button>
    </>
    )}
    </CardContent>
    </Card>
    </motion.div>
    </div>
    );
    }

    // If no manga matches are loaded yet, show loading state
    if (mangaMatches.length === 0) {
    return (
    <div className="container py-6">
    <motion.div
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    transition={{ duration: 0.4 }}
    >
    <Card className="mx-auto w-full max-w-md text-center">
    <CardContent className="pt-6">
    <div
    className="mb-4 inline-block h-8 w-8 animate-spin rounded-full border-4 border-current border-t-transparent text-blue-600"
    role="status"
    aria-label="loading"
    >
    <span className="sr-only">Loading...</span>
    </div>
    <h3 className="text-lg font-medium">
    Loading Synchronization Data
    </h3>
    <p className="mt-2 text-sm text-slate-500">
    Please wait while we load your matched manga data...
    </p>
    </CardContent>
    </Card>
    </motion.div>
    </div>
    );
    }

    // If library is loading, show loading state
    if (libraryLoading) {
    return (
    <div className="container py-6">
    <motion.div
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    transition={{ duration: 0.4 }}
    >
    <Card className="mx-auto w-full max-w-md text-center">
    <CardContent className="pt-6">
    <div
    className="mb-4 inline-block h-8 w-8 animate-spin rounded-full border-4 border-current border-t-transparent text-blue-600"
    role="status"
    aria-label="loading"
    >
    <span className="sr-only">Loading...</span>
    </div>
    <h3 className="text-lg font-medium">
    {rateLimitState.isRateLimited
    ? "Synchronization Paused"
    : "Loading Your AniList Library"}
    </h3>
    {!rateLimitState.isRateLimited && (
    <p className="mt-2 text-sm text-slate-500">
    {retryCount > 0
    ? `Server error encountered. Retrying (${retryCount}/${maxRetries})...`
    : "Please wait while we fetch your AniList library data for comparison..."}
    </p>
    )}
    </CardContent>
    </Card>
    </motion.div>
    </div>
    );
    }

    // Render the appropriate view based on state
    const renderContent = () => {
    switch (viewMode) {
    case "preview":
    return (
    <motion.div
    className="space-y-6"
    key="preview"
    initial="hidden"
    animate="visible"
    exit="exit"
    variants={staggerContainerVariants}
    >
    <motion.div variants={cardVariants}>
    <Card>
    <CardHeader>
    <CardTitle>Sync Preview</CardTitle>
    <CardDescription>
    Review the changes that will be applied to your AniList
    account
    </CardDescription>
    </CardHeader>
    <CardContent>
    {/* Sync Configuration */}
    <Collapsible className="mb-4">
    <CollapsibleTrigger asChild>
    <Button
    variant="outline"
    className="flex w-full items-center justify-between p-3"
    >
    <span className="flex items-center gap-2">
    <Settings className="h-4 w-4" />
    Sync Configuration
    </span>
    <span className="text-muted-foreground text-xs">
    Click to expand
    </span>
    </Button>
    </CollapsibleTrigger>
    <CollapsibleContent className="mt-2 rounded-md border bg-slate-50 p-4 dark:bg-slate-900">
    <div className="space-y-4">
    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="prioritizeAniListStatus"
    className="flex-1 text-sm"
    >
    Prioritize AniList status
    <span className="text-muted-foreground block text-xs">
    When enabled, keeps your existing AniList status
    </span>
    </Label>
    <Switch
    id="prioritizeAniListStatus"
    checked={syncConfig.prioritizeAniListStatus}
    onCheckedChange={() =>
    handleToggleOption("prioritizeAniListStatus")
    }
    />
    </div>
    </div>

    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="preserveCompletedStatus"
    className="flex-1 text-sm"
    >
    Preserve Completed Status
    <span className="text-muted-foreground block text-xs">
    Always preserve entries marked as COMPLETED in
    AniList
    </span>
    </Label>
    <Switch
    id="preserveCompletedStatus"
    checked={syncConfig.preserveCompletedStatus}
    onCheckedChange={() =>
    handleToggleOption("preserveCompletedStatus")
    }
    />
    </div>
    </div>

    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="prioritizeAniListProgress"
    className="flex-1 text-sm"
    >
    Prioritize AniList progress
    <span className="text-muted-foreground block text-xs">
    When enabled, keeps higher chapter counts from
    AniList (Does not apply when the prioritized
    source is 0 or none/null)
    </span>
    </Label>
    <Switch
    id="prioritizeAniListProgress"
    checked={syncConfig.prioritizeAniListProgress}
    onCheckedChange={() =>
    handleToggleOption("prioritizeAniListProgress")
    }
    />
    </div>
    </div>

    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="prioritizeAniListScore"
    className="flex-1 text-sm"
    >
    Prioritize AniList scores
    <span className="text-muted-foreground block text-xs">
    When enabled, keeps your existing AniList scores
    (Does not apply when the prioritized source is
    none/null)
    </span>
    </Label>
    <Switch
    id="prioritizeAniListScore"
    checked={syncConfig.prioritizeAniListScore}
    onCheckedChange={() =>
    handleToggleOption("prioritizeAniListScore")
    }
    />
    </div>
    </div>

    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="setPrivate"
    className="flex-1 text-sm"
    >
    Set entries as private
    <span className="text-muted-foreground block text-xs">
    When enabled, sets entries as private.
    Doesn&apos;t change existing private settings.
    </span>
    </Label>
    <Switch
    id="setPrivate"
    checked={syncConfig.setPrivate}
    onCheckedChange={() =>
    handleToggleOption("setPrivate")
    }
    />
    </div>
    </div>

    <div className="flex flex-col gap-2">
    <div className="flex items-center justify-between">
    <Label
    htmlFor="autoPauseInactive"
    className="flex-1 text-sm"
    >
    Auto-pause inactive manga
    <span className="text-muted-foreground block text-xs">
    When enabled, sets manga as PAUSED if not
    updated recently (Can specify the period)
    </span>
    </Label>
    <Switch
    id="autoPauseInactive"
    checked={syncConfig.autoPauseInactive}
    onCheckedChange={() =>
    handleToggleOption("autoPauseInactive")
    }
    />
    </div>
    </div>

    {syncConfig.autoPauseInactive && (
    <div className="mt-2 border-l-2 border-slate-200 pl-2 dark:border-slate-700">
    <div className="flex items-center gap-2">
    <Label
    htmlFor="autoPauseThreshold"
    className="text-sm whitespace-nowrap"
    >
    Pause after
    </Label>
    {!useCustomThreshold ? (
    <select
    id="autoPauseThreshold"
    value={syncConfig.autoPauseThreshold}
    onChange={(e) => {
    const value = e.target.value;
    if (value === "custom") {
    setUseCustomThreshold(true);
    } else {
    setSyncConfig((prev) => {
    const newConfig = {
    ...prev,
    autoPauseThreshold: Number(value),
    };
    saveSyncConfig(newConfig);
    return newConfig;
    });
    }
    }}
    className="border-input bg-background focus-visible:ring-ring h-8 w-full rounded-md border px-3 py-1 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none"
    >
    <option value="1">1 day</option>
    <option value="7">7 days</option>
    <option value="14">14 days</option>
    <option value="30">30 days</option>
    <option value="60">2 months</option>
    <option value="90">3 months</option>
    <option value="180">6 months</option>
    <option value="365">1 year</option>
    <option value="custom">Custom...</option>
    </select>
    ) : (
    <div className="flex w-full items-center gap-2">
    <input
    id="customAutoPauseThreshold"
    type="number"
    min="1"
    placeholder="Enter days"
    value={syncConfig.autoPauseThreshold.toString()}
    onChange={(e) => {
    const value = parseInt(e.target.value);
    if (!isNaN(value) && value > 0) {
    setSyncConfig((prev) => {
    const newConfig = {
    ...prev,
    autoPauseThreshold: value,
    };
    saveSyncConfig(newConfig);
    return newConfig;
    });
    }
    }}
    className="border-input bg-background focus-visible:ring-ring h-8 w-full rounded-md border px-3 py-1 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none"
    />
    <Button
    variant="outline"
    className="h-8 px-2"
    onClick={() => setUseCustomThreshold(false)}
    >
    Use Presets
    </Button>
    </div>
    )}
    </div>

    <p className="text-muted-foreground mt-1 text-xs">
    Manga not updated for this period will be set to
    PAUSED
    </p>
    </div>
    )}
    </div>
    </CollapsibleContent>
    </Collapsible>

    {/* Summary of changes */}
    <div className="mb-6 rounded-md border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-900/20">
    <h3 className="flex items-center text-sm font-medium">
    <AlertCircle className="mr-2 h-4 w-4 text-amber-500" />
    Changes Summary
    </h3>
    <p className="text-muted-foreground mt-1 text-sm">
    {entriesWithChanges.length} entries will be synchronized
    to your AniList account.
    </p>

    {libraryLoading && (
    <div className="text-muted-foreground mt-2 flex items-center gap-2 text-xs">
    <Loader2 className="h-3 w-3 animate-spin" />
    Loading your AniList library for comparison...
    </div>
    )}

    {libraryError && (
    <div className="mt-2 flex items-center gap-2 text-xs text-amber-600 dark:text-amber-400">
    <AlertCircle className="h-3 w-3" />
    {!rateLimitState.isRateLimited && (
    <span>{libraryError}</span>
    )}

    {/* Only show Try Again button when not rate limited */}
    {!rateLimitState.isRateLimited && (
    <Button
    variant="link"
    className="h-auto px-0 py-0 text-xs"
    onClick={() => {
    setLibraryLoading(true);
    setLibraryError(null);
    setRetryCount(0);
    setRateLimit(false, undefined, undefined);

    const controller = new AbortController();

    getUserMangaList(token, controller.signal)
    .then((library) => {
    console.log(
    `Loaded ${Object.keys(library).length} entries from user's AniList library`,
    );
    setUserLibrary(library);
    setLibraryLoading(false);
    })
    .catch((error) => {
    if (error.name !== "AbortError") {
    console.error(
    "Failed to load user library again:",
    error,
    );

    // Check for rate limiting - with our new client updates, this should be more reliable
    if (
    error.isRateLimited ||
    error.status === 429
    ) {
    console.warn(
    "📛 DETECTED RATE LIMIT in SyncPage:",
    {
    isRateLimited: error.isRateLimited,
    status: error.status,
    retryAfter: error.retryAfter,
    },
    );

    const retryDelay = error.retryAfter
    ? error.retryAfter
    : 60;
    const retryTimestamp =
    Date.now() + retryDelay;

    console.log(
    `Setting rate limited state with retry after: ${retryTimestamp} (in ${retryDelay / 1000}s)`,
    );

    setRateLimit(
    true,
    retryDelay,
    "AniList API rate limit reached. Waiting to retry...",
    );
    } else {
    setLibraryError(
    error.message ||
    "Failed to load your AniList library. Synchronization can still proceed without comparison data.",
    );
    }

    setUserLibrary({});
    setLibraryLoading(false);
    }
    });
    }}
    >
    Try Again
    </Button>
    )}
    </div>
    )}

    {!libraryLoading &&
    !libraryError &&
    userLibrary &&
    Object.keys(userLibrary).length > 0 && (
    <div className="mt-2 flex items-center justify-between">
    <div className="flex items-center gap-2 text-xs text-emerald-600 dark:text-emerald-400">
    <div className="h-3 w-3 rounded-full bg-emerald-500"></div>
    <span>
    Found{" "}
    <span className="font-semibold">
    {Object.keys(userLibrary).length}
    </span>{" "}
    unique entries in your AniList library for
    comparison
    </span>
    </div>
    <Button
    variant="outline"
    size="sm"
    className="h-7 text-xs"
    onClick={() => {
    setLibraryLoading(true);
    setLibraryError(null);
    setRetryCount(0);
    setRateLimit(false, undefined, undefined);

    const controller = new AbortController();

    getUserMangaList(token, controller.signal)
    .then((library) => {
    console.log(
    `Loaded ${Object.keys(library).length} entries from user's AniList library`,
    );
    setUserLibrary(library);
    setLibraryLoading(false);
    })
    .catch((error) => {
    if (error.name !== "AbortError") {
    console.error(
    "Failed to load user library again:",
    error,
    );

    // Check for rate limiting - with our new client updates, this should be more reliable
    if (
    error.isRateLimited ||
    error.status === 429
    ) {
    console.warn(
    "📛 DETECTED RATE LIMIT in SyncPage:",
    {
    isRateLimited: error.isRateLimited,
    status: error.status,
    retryAfter: error.retryAfter,
    },
    );

    const retryDelay = error.retryAfter
    ? error.retryAfter
    : 60;
    const retryTimestamp =
    Date.now() + retryDelay;

    console.log(
    `Setting rate limited state with retry after: ${retryTimestamp} (in ${retryDelay / 1000}s)`,
    );

    setRateLimit(
    true,
    retryDelay,
    "AniList API rate limit reached. Waiting to retry...",
    );
    } else {
    setLibraryError(
    error.message ||
    "Failed to load your AniList library. Synchronization can still proceed without comparison data.",
    );
    }

    setUserLibrary({});
    setLibraryLoading(false);
    }
    });
    }}
    >
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="14"
    height="14"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    className="mr-1"
    >
    <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" />
    <path d="M21 3v5h-5" />
    <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" />
    <path d="M8 16H3v5" />
    </svg>
    Refresh
    </Button>
    </div>
    )}

    {!libraryLoading && !libraryError && (
    <div className="mt-4 rounded bg-blue-50 p-2 text-xs text-blue-600 dark:bg-blue-900/20 dark:text-blue-400">
    <div className="mb-1 font-semibold">
    Manga Statistics:
    </div>
    <div className="grid grid-cols-2 gap-x-4 gap-y-1">
    <div>
    <span className="text-slate-600 dark:text-slate-400">
    Kenmei manga:
    </span>{" "}
    {mangaMatches.length}
    </div>
    <div>
    <span className="text-slate-600 dark:text-slate-400">
    AniList library:
    </span>{" "}
    {Object.keys(userLibrary).length}
    </div>
    <div>
    <span className="text-slate-600 dark:text-slate-400">
    New entries:
    </span>{" "}
    {
    mangaMatches.filter(
    (match) =>
    match.selectedMatch &&
    !userLibrary[match.selectedMatch.id],
    ).length
    }
    </div>
    <div>
    <span className="text-slate-600 dark:text-slate-400">
    Updates:
    </span>{" "}
    {
    mangaMatches.filter((match) => {
    // Only count manga that will actually have changes
    if (!match.selectedMatch) return false;

    const anilist = match.selectedMatch;
    const kenmei = match.kenmeiManga;
    const userEntry = userLibrary[anilist.id];

    // Skip if not in user library or if completed and we're preserving completed status
    if (
    !userEntry ||
    (userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus)
    ) {
    return false;
    }

    // Check if any values will change based on sync configuration
    const statusWillChange = userEntry
    ? syncConfig.prioritizeAniListStatus
    ? false
    : getEffectiveStatus(kenmei) !==
    userEntry.status
    : true;

    const progressWillChange =
    syncConfig.prioritizeAniListProgress
    ? // Will only change if Kenmei has more chapters read than AniList
    (kenmei.chapters_read || 0) >
    (userEntry.progress || 0)
    : (kenmei.chapters_read || 0) !==
    (userEntry.progress || 0);

    const anilistScore = Number(
    userEntry.score || 0,
    );
    const kenmeiScore = Number(kenmei.score || 0);
    const scoreWillChange =
    syncConfig.prioritizeAniListScore &&
    userEntry.score &&
    Number(userEntry.score) > 0
    ? false
    : kenmei.score > 0 &&
    (anilistScore === 0 ||
    Math.abs(kenmeiScore - anilistScore) >=
    0.5);

    // Check if privacy will change
    const privacyWillChange =
    syncConfig.setPrivate && !userEntry.private;

    // Count entry only if at least one value will change
    return (
    statusWillChange ||
    progressWillChange ||
    scoreWillChange ||
    privacyWillChange
    );
    }).length
    }
    </div>
    </div>

    <div className="mt-2 border-t border-blue-200 pt-2 text-amber-600 dark:border-blue-800 dark:text-amber-400">
    <strong className="text-xs">Note:</strong> Media
    entries with &ldquo;Hide from status lists&rdquo;
    option set to true and not associated with any custom
    lists will not be returned by the query and will be
    treated as not in your library.
    </div>
    </div>
    )}
    </div>

    <div className="mb-4 flex items-center justify-between">
    {/* Display Mode Toggle */}
    <div className="flex items-center gap-2">
    <span className="text-muted-foreground text-sm">
    View:
    </span>
    <div className="border-input bg-background inline-flex items-center rounded-md border p-1">
    <Button
    variant={
    displayMode === "cards" ? "default" : "ghost"
    }
    size="sm"
    className="h-8 rounded-sm px-2"
    onClick={() => setDisplayMode("cards")}
    >
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    className="mr-1"
    >
    <rect width="7" height="7" x="3" y="3" rx="1" />
    <rect width="7" height="7" x="14" y="3" rx="1" />
    <rect width="7" height="7" x="14" y="14" rx="1" />
    <rect width="7" height="7" x="3" y="14" rx="1" />
    </svg>
    Cards
    </Button>
    <Button
    variant={
    displayMode === "compact" ? "default" : "ghost"
    }
    size="sm"
    className="h-8 rounded-sm px-2"
    onClick={() => setDisplayMode("compact")}
    >
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    className="mr-1"
    >
    <line x1="3" x2="21" y1="6" y2="6" />
    <line x1="3" x2="21" y1="12" y2="12" />
    <line x1="3" x2="21" y1="18" y2="18" />
    </svg>
    Compact
    </Button>
    </div>
    </div>

    <div className="flex gap-2">
    {/* Sort Dropdown - Improved */}
    <DropdownMenu>
    <DropdownMenuTrigger asChild>
    <Button variant="outline" size="sm" className="h-8">
    <SortAsc className="mr-1 h-4 w-4" />
    Sort
    {sortOption.field !== "title" ||
    sortOption.direction !== "asc" ? (
    <span className="ml-1 text-xs opacity-70">
    (
    {sortOption.field.charAt(0).toUpperCase() +
    sortOption.field.slice(1)}
    , {sortOption.direction === "asc" ? "↑" : "↓"})
    </span>
    ) : null}
    <span className="sr-only">Sort</span>
    </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end" className="w-56">
    <div className="p-2">
    <div className="mb-2 flex items-center justify-between">
    <DropdownMenuLabel className="p-0">
    Sort by
    </DropdownMenuLabel>
    <div className="flex overflow-hidden rounded-md border">
    <Button
    variant={
    sortOption.direction === "asc"
    ? "default"
    : "outline"
    }
    size="sm"
    className="h-7 rounded-none border-0 px-2"
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    direction: "asc",
    }))
    }
    >
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    >
    <path d="m3 8 4-4 4 4" />
    <path d="M7 4v16" />
    <path d="M11 12h4" />
    <path d="M11 16h7" />
    <path d="M11 20h10" />
    </svg>
    <span className="sr-only">Ascending</span>
    </Button>
    <Button
    variant={
    sortOption.direction === "desc"
    ? "default"
    : "outline"
    }
    size="sm"
    className="h-7 rounded-none border-0 px-2"
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    direction: "desc",
    }))
    }
    >
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    >
    <path d="m3 16 4 4 4-4" />
    <path d="M7 20V4" />
    <path d="M11 4h4" />
    <path d="M11 8h7" />
    <path d="M11 12h10" />
    </svg>
    <span className="sr-only">Descending</span>
    </Button>
    </div>
    </div>
    </div>
    <DropdownMenuSeparator />
    <DropdownMenuItem
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    field: "title",
    }))
    }
    className="flex justify-between"
    >
    Title
    {sortOption.field === "title" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    field: "status",
    }))
    }
    className="flex justify-between"
    >
    Status
    {sortOption.field === "status" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    field: "progress",
    }))
    }
    className="flex justify-between"
    >
    Progress
    {sortOption.field === "progress" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    field: "score",
    }))
    }
    className="flex justify-between"
    >
    Score
    {sortOption.field === "score" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setSortOption((prev) => ({
    ...prev,
    field: "changes",
    }))
    }
    className="flex justify-between"
    >
    Changes count
    {sortOption.field === "changes" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    </DropdownMenuContent>
    </DropdownMenu>

    {/* Filter Dropdown */}
    <DropdownMenu>
    <DropdownMenuTrigger asChild>
    <Button variant="outline" size="sm" className="h-8">
    <Filter className="mr-1 h-4 w-4" />
    Filter
    <span className="sr-only">Filter</span>
    </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end" className="w-48">
    <DropdownMenuLabel>
    Filter by Status
    </DropdownMenuLabel>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({ ...prev, status: "all" }))
    }
    className="flex justify-between"
    >
    All statuses
    {filters.status === "all" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    status: "reading",
    }))
    }
    className="flex justify-between"
    >
    Reading
    {filters.status === "reading" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    status: "completed",
    }))
    }
    className="flex justify-between"
    >
    Completed
    {filters.status === "completed" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    status: "planned",
    }))
    }
    className="flex justify-between"
    >
    Plan to Read
    {filters.status === "planned" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    status: "paused",
    }))
    }
    className="flex justify-between"
    >
    On Hold
    {filters.status === "paused" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    status: "dropped",
    }))
    }
    className="flex justify-between"
    >
    Dropped
    {filters.status === "dropped" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>

    <DropdownMenuSeparator />
    <DropdownMenuLabel>
    Filter by Changes
    </DropdownMenuLabel>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    changes: "all",
    }))
    }
    className="flex justify-between"
    >
    All entries
    {filters.changes === "all" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    changes: "with-changes",
    }))
    }
    className="flex justify-between"
    >
    With changes
    {filters.changes === "with-changes" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    changes: "no-changes",
    }))
    }
    className="flex justify-between"
    >
    No changes
    {filters.changes === "no-changes" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>

    <DropdownMenuSeparator />
    <DropdownMenuLabel>
    Filter by Library
    </DropdownMenuLabel>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    library: "all",
    }))
    }
    className="flex justify-between"
    >
    All entries
    {filters.library === "all" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    library: "new",
    }))
    }
    className="flex justify-between"
    >
    New to library
    {filters.library === "new" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    <DropdownMenuItem
    onClick={() =>
    setFilters((prev) => ({
    ...prev,
    library: "existing",
    }))
    }
    className="flex justify-between"
    >
    Already in library
    {filters.library === "existing" && (
    <Check className="h-4 w-4" />
    )}
    </DropdownMenuItem>
    </DropdownMenuContent>
    </DropdownMenu>

    <Button
    variant="ghost"
    size="sm"
    className="h-8"
    onClick={() => {
    setSortOption({ field: "title", direction: "asc" });
    setFilters({
    status: "all",
    changes: "all",
    library: "all",
    });
    }}
    >
    Reset
    </Button>
    </div>
    </div>

    {/* Results counter */}
    {sortedMangaMatches.length !== mangaMatches.length && (
    <div className="bg-muted/30 mb-4 flex items-center justify-between rounded-md px-3 py-2 text-sm">
    <div>
    Showing{" "}
    <span className="font-medium">
    {sortedMangaMatches.length}
    </span>{" "}
    of{" "}
    <span className="font-medium">
    {
    mangaMatches.filter(
    (match) => match.status !== "skipped",
    ).length
    }
    </span>{" "}
    manga
    {Object.values(filters).some((v) => v !== "all") && (
    <span className="text-muted-foreground ml-1">
    (filtered)
    </span>
    )}
    </div>
    <Button
    variant="ghost"
    size="sm"
    className="h-7 text-xs"
    onClick={() => {
    setSortOption({ field: "title", direction: "asc" });
    setFilters({
    status: "all",
    changes: "all",
    library: "all",
    });
    }}
    >
    Clear Filters
    </Button>
    </div>
    )}

    <div className="max-h-[60vh] overflow-y-auto">
    <AnimatePresence
    initial={false}
    mode="wait"
    key={displayMode}
    >
    {displayMode === "cards" ? (
    <motion.div
    key="cards-view"
    variants={fadeVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    transition={viewModeTransition}
    className="grid grid-cols-1 gap-4"
    >
    <AnimatePresence initial={false}>
    {sortedMangaMatches
    .slice(0, visibleItems)
    .map((match, index) => {
    const kenmei = match.kenmeiManga;
    const anilist = match.selectedMatch!;

    // Get the user's existing data for this manga if it exists
    const userEntry = userLibrary[anilist.id];

    // Determine what will change based on sync configuration
    const statusWillChange = userEntry
    ? syncConfig.prioritizeAniListStatus
    ? false // If prioritizing AniList status, it won't change
    : getEffectiveStatus(kenmei) !==
    userEntry.status &&
    !(
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    )
    : true;

    const progressWillChange = userEntry
    ? syncConfig.prioritizeAniListProgress
    ? // Will only change if Kenmei has more chapters read than AniList
    (kenmei.chapters_read || 0) >
    (userEntry.progress || 0)
    : (kenmei.chapters_read || 0) !==
    (userEntry.progress || 0)
    : true;

    const scoreWillChange = userEntry
    ? // Don't update completed entries if preserve setting is on
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ? false
    : // Apply score prioritization rules
    syncConfig.prioritizeAniListScore &&
    userEntry.score &&
    Number(userEntry.score) > 0
    ? false // Only prioritize if AniList score > 0
    : // Only consider a change if Kenmei has a score
    kenmei.score > 0 &&
    // Convert both scores to numbers and compare
    // If AniList has no score but Kenmei does, that's a change
    (Number(userEntry.score || 0) === 0 ||
    // Use threshold comparison after explicit number conversion
    Math.abs(
    Number(kenmei.score) -
    Number(userEntry.score || 0),
    ) >= 0.5)
    : // For new entries, only show score change if Kenmei has a score
    kenmei.score > 0;

    // Track if manga is new to the user's library or shouldn't be updated due to special cases
    const isNewEntry = !userEntry;
    const isCompleted =
    userEntry && userEntry.status === "COMPLETED";

    // Count the number of changes
    const changeCount = [
    statusWillChange,
    progressWillChange,
    scoreWillChange,
    userEntry
    ? syncConfig.setPrivate &&
    !userEntry.private
    : syncConfig.setPrivate,
    ].filter(Boolean).length;

    return (
    <motion.div
    key={`${anilist.id}-${index}`}
    layout="position"
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    exit={{ opacity: 0, scale: 0.9 }}
    transition={{ duration: 0.3 }}
    layoutId={undefined}
    >
    <Card className="overflow-hidden transition-shadow duration-200 hover:shadow-md">
    <div className="flex">
    {/* Manga Cover Image - Updated styling */}
    <div className="relative flex h-[200px] flex-shrink-0 items-center justify-center pl-3">
    {anilist.coverImage?.large ||
    anilist.coverImage?.medium ? (
    <motion.div
    layout="position"
    animate={{
    transition: { type: false },
    }}
    >
    <img
    src={
    anilist.coverImage?.large ||
    anilist.coverImage?.medium
    }
    alt={anilist.title.romaji || ""}
    className="h-full w-[145px] rounded-sm object-cover"
    />
    </motion.div>
    ) : (
    <div className="flex h-[200px] items-center justify-center rounded-sm bg-slate-200 dark:bg-slate-800">
    <span className="text-muted-foreground text-xs">
    No Cover
    </span>
    </div>
    )}

    {/* Status Badges - Removed Manual badge */}
    <div className="absolute top-2 left-4 flex flex-col gap-1">
    {isNewEntry && (
    <Badge className="bg-emerald-500">
    New
    </Badge>
    )}
    {isCompleted && (
    <Badge
    variant="outline"
    className="border-amber-500 text-amber-700 dark:text-amber-400"
    >
    Completed
    </Badge>
    )}
    </div>
    </div>

    {/* Content */}
    <div className="flex-1 p-4">
    <div className="flex items-start justify-between">
    <div>
    <h3 className="line-clamp-2 max-w-[580px] text-base font-semibold">
    {anilist.title.romaji ||
    kenmei.title}
    </h3>
    {changeCount > 0 &&
    !isCompleted ? (
    <div className="mt-1 flex flex-wrap gap-1">
    {statusWillChange && (
    <Badge
    variant="outline"
    className="border-blue-400 px-1.5 py-0 text-xs text-blue-600 dark:text-blue-400"
    >
    Status
    </Badge>
    )}

    {progressWillChange && (
    <Badge
    variant="outline"
    className="border-green-400 px-1.5 py-0 text-xs text-green-600 dark:text-green-400"
    >
    Progress
    </Badge>
    )}

    {scoreWillChange && (
    <Badge
    variant="outline"
    className="border-amber-400 px-1.5 py-0 text-xs text-amber-600 dark:text-amber-400"
    >
    Score
    </Badge>
    )}

    {userEntry
    ? syncConfig.setPrivate &&
    !userEntry.private && (
    <Badge
    variant="outline"
    className="border-purple-400 px-1.5 py-0 text-xs text-purple-600 dark:text-purple-400"
    >
    Privacy
    </Badge>
    )
    : syncConfig.setPrivate && (
    <Badge
    variant="outline"
    className="border-purple-400 px-1.5 py-0 text-xs text-purple-600 dark:text-purple-400"
    >
    Privacy
    </Badge>
    )}
    </div>
    ) : (
    <div className="mt-1">
    <Badge
    variant="outline"
    className="text-muted-foreground px-1.5 py-0 text-xs"
    >
    {isCompleted
    ? "Preserving Completed"
    : "No Changes"}
    </Badge>
    </div>
    )}
    </div>

    {/* Change Indicator */}
    {changeCount > 0 &&
    !isCompleted && (
    <div className="rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-600 dark:bg-blue-900/30 dark:text-blue-300">
    {changeCount} change
    {changeCount !== 1 ? "s" : ""}
    </div>
    )}
    </div>

    {/* Comparison Table */}
    <div className="mt-4 grid grid-cols-2 gap-2 text-sm">
    <div
    className={`rounded-md p-2 ${isNewEntry ? "bg-slate-100 dark:bg-slate-800/60" : "bg-slate-100 dark:bg-slate-800/60"}`}
    >
    <h4 className="text-muted-foreground mb-2 text-xs font-medium">
    {isNewEntry
    ? "Not in Library"
    : "Current AniList"}
    </h4>

    {isNewEntry ? (
    <div className="text-muted-foreground py-4 text-center text-xs">
    New addition to your library
    </div>
    ) : (
    <div className="space-y-2">
    <div className="flex items-center justify-between">
    <span className="text-muted-foreground text-xs">
    Status:
    </span>
    <span
    className={`text-xs font-medium ${statusWillChange ? "text-muted-foreground line-through" : ""}`}
    >
    {userEntry?.status ||
    "None"}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-muted-foreground text-xs">
    Progress:
    </span>
    <span
    className={`text-xs font-medium ${progressWillChange ? "text-muted-foreground line-through" : ""}`}
    >
    {userEntry?.progress || 0}{" "}
    ch
    {anilist.chapters
    ? ` / ${anilist.chapters}`
    : ""}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-muted-foreground text-xs">
    Score:
    </span>
    <span
    className={`text-xs font-medium ${scoreWillChange ? "text-muted-foreground line-through" : ""}`}
    >
    {userEntry?.score
    ? `${userEntry.score}/10`
    : "None"}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-muted-foreground text-xs">
    Private:
    </span>
    <span
    className={`text-xs font-medium ${userEntry ? (syncConfig.setPrivate && !userEntry.private ? "text-muted-foreground line-through" : "") : syncConfig.setPrivate ? "text-muted-foreground line-through" : ""}`}
    >
    {userEntry?.private
    ? "Yes"
    : "No"}
    </span>
    </div>
    </div>
    )}
    </div>

    <div className="rounded-md bg-blue-50 p-2 dark:bg-blue-900/20">
    <h4 className="mb-2 text-xs font-medium text-blue-600 dark:text-blue-300">
    After Sync
    </h4>

    <div className="space-y-2">
    <div className="flex items-center justify-between">
    <span className="text-xs text-blue-500 dark:text-blue-400">
    Status:
    </span>
    <span
    className={`text-xs font-medium ${statusWillChange ? "text-blue-700 dark:text-blue-300" : ""}`}
    >
    {getEffectiveStatus(kenmei)}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-xs text-blue-500 dark:text-blue-400">
    Progress:
    </span>
    <span
    className={`text-xs font-medium ${progressWillChange ? "text-blue-700 dark:text-blue-300" : ""}`}
    >
    {syncConfig.prioritizeAniListProgress
    ? userEntry?.progress &&
    userEntry.progress > 0
    ? (kenmei.chapters_read ||
    0) >
    userEntry.progress
    ? kenmei.chapters_read ||
    0
    : userEntry.progress
    : kenmei.chapters_read ||
    0
    : kenmei.chapters_read ||
    0}{" "}
    ch
    {anilist.chapters
    ? ` / ${anilist.chapters}`
    : ""}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-xs text-blue-500 dark:text-blue-400">
    Score:
    </span>
    <span
    className={`text-xs font-medium ${scoreWillChange ? "text-blue-700 dark:text-blue-300" : ""}`}
    >
    {scoreWillChange
    ? kenmei.score
    ? `${kenmei.score}/10`
    : "None"
    : userEntry?.score
    ? `${userEntry.score}/10`
    : "None"}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-xs text-blue-500 dark:text-blue-400">
    Private:
    </span>
    <span
    className={`text-xs font-medium ${userEntry ? (syncConfig.setPrivate && !userEntry.private ? "text-blue-700 dark:text-blue-300" : "") : syncConfig.setPrivate ? "text-blue-700 dark:text-blue-300" : ""}`}
    >
    {userEntry
    ? syncConfig.setPrivate
    ? "Yes"
    : userEntry.private
    ? "Yes"
    : "No"
    : syncConfig.setPrivate
    ? "Yes"
    : "No"}
    </span>
    </div>
    </div>
    </div>
    </div>
    </div>
    </div>
    </Card>
    </motion.div>
    );
    })}
    </AnimatePresence>

    {/* Load more button instead of automatic loading */}
    {sortedMangaMatches.length > visibleItems ? (
    <div className="py-4 text-center">
    <Button
    onClick={() => {
    setIsLoadingMore(true);
    const newValue = Math.min(
    visibleItems + 20,
    sortedMangaMatches.length,
    );
    console.log(
    `Loading more items: ${visibleItems} → ${newValue}`,
    );

    // Add a small delay to show the loading spinner
    setTimeout(() => {
    setVisibleItems(newValue);
    setIsLoadingMore(false);
    }, 300);
    }}
    variant="outline"
    className="gap-2"
    disabled={isLoadingMore}
    >
    {isLoadingMore && (
    <div className="text-primary inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"></div>
    )}
    {isLoadingMore
    ? "Loading..."
    : `Load More (${visibleItems} of ${sortedMangaMatches.length})`}
    </Button>
    </div>
    ) : sortedMangaMatches.length > 0 ? (
    <div className="py-4 text-center">
    <span className="text-muted-foreground text-xs">
    All items loaded
    </span>
    </div>
    ) : null}
    </motion.div>
    ) : (
    <motion.div
    key="compact-view"
    variants={fadeVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    transition={viewModeTransition}
    className="space-y-1 overflow-hidden rounded-md border"
    >
    <AnimatePresence initial={false}>
    {sortedMangaMatches
    .slice(0, visibleItems)
    .map((match, index) => {
    const kenmei = match.kenmeiManga;
    const anilist = match.selectedMatch!;

    // Get the user's existing data for this manga if it exists
    const userEntry = userLibrary[anilist.id];

    // Determine what will change based on sync configuration
    const statusWillChange = userEntry
    ? syncConfig.prioritizeAniListStatus
    ? false // If prioritizing AniList status, it won't change
    : getEffectiveStatus(kenmei) !==
    userEntry.status &&
    !(
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    )
    : true;

    const progressWillChange = userEntry
    ? syncConfig.prioritizeAniListProgress
    ? // Will only change if Kenmei has more chapters read than AniList
    (kenmei.chapters_read || 0) >
    (userEntry.progress || 0)
    : (kenmei.chapters_read || 0) !==
    (userEntry.progress || 0)
    : true;

    const scoreWillChange = userEntry
    ? // Don't update completed entries if preserve setting is on
    userEntry.status === "COMPLETED" &&
    syncConfig.preserveCompletedStatus
    ? false
    : // Apply score prioritization rules
    syncConfig.prioritizeAniListScore &&
    userEntry.score &&
    Number(userEntry.score) > 0
    ? false // Only prioritize if AniList score > 0
    : // Only consider a change if Kenmei has a score
    kenmei.score > 0 &&
    // Convert both scores to numbers and compare
    // If AniList has no score but Kenmei does, that's a change
    (Number(userEntry.score || 0) === 0 ||
    // Use threshold comparison after explicit number conversion
    Math.abs(
    Number(kenmei.score) -
    Number(userEntry.score || 0),
    ) >= 0.5)
    : // For new entries, only show score change if Kenmei has a score
    kenmei.score > 0;

    // Track if manga is new to the user's library or shouldn't be updated due to special cases
    const isNewEntry = !userEntry;
    const isCompleted =
    userEntry && userEntry.status === "COMPLETED";

    // Count the number of changes
    const changeCount = [
    statusWillChange,
    progressWillChange,
    scoreWillChange,
    userEntry
    ? syncConfig.setPrivate &&
    !userEntry.private
    : syncConfig.setPrivate,
    ].filter(Boolean).length;

    return (
    <motion.div
    key={`${anilist.id}-${index}`}
    layout="position"
    initial={{ opacity: 0, y: 5 }}
    animate={{ opacity: 1, y: 0 }}
    exit={{ opacity: 0 }}
    transition={{ duration: 0.2 }}
    layoutId={undefined}
    >
    <div
    className={`hover:bg-muted/50 flex items-center px-3 py-2 ${index % 2 === 0 ? "bg-muted/30" : ""} ${isCompleted ? "bg-amber-50/50 dark:bg-amber-950/20" : ""} ${isNewEntry ? "bg-emerald-50/50 dark:bg-emerald-950/20" : ""}`}
    >
    {/* Thumbnail - Updated styling */}
    <div className="mr-3 flex flex-shrink-0 items-center pl-2">
    {anilist.coverImage?.large ||
    anilist.coverImage?.medium ? (
    <motion.div
    layout="position"
    animate={{
    transition: { type: false },
    }}
    >
    <img
    src={
    anilist.coverImage?.large ||
    anilist.coverImage?.medium
    }
    alt={anilist.title.romaji || ""}
    className="h-12 w-8 rounded-sm object-cover"
    />
    </motion.div>
    ) : (
    <div className="flex h-12 w-8 items-center justify-center rounded-sm bg-slate-200 dark:bg-slate-800">
    <span className="text-muted-foreground text-[8px]">
    No Cover
    </span>
    </div>
    )}
    </div>

    {/* Title and status */}
    <div className="mr-2 min-w-0 flex-1">
    <div className="truncate text-sm font-medium">
    {anilist.title.romaji || kenmei.title}
    </div>
    <div className="mt-0.5 flex items-center gap-1">
    {isNewEntry && (
    <Badge className="px-1 py-0 text-[10px]">
    New
    </Badge>
    )}
    {isCompleted && (
    <Badge
    variant="outline"
    className="border-amber-500 px-1 py-0 text-[10px] text-amber-700"
    >
    Completed
    </Badge>
    )}
    </div>
    </div>

    {/* Changes */}
    <div className="flex flex-shrink-0 items-center gap-1">
    {!isNewEntry && !isCompleted && (
    <>
    {statusWillChange && (
    <Badge
    variant="outline"
    className="border-blue-400 px-1 py-0 text-[10px]"
    >
    {userEntry?.status || "None"} →{" "}
    {getEffectiveStatus(kenmei)}
    </Badge>
    )}

    {progressWillChange && (
    <Badge
    variant="outline"
    className="border-green-400 px-1 py-0 text-[10px]"
    >
    {userEntry?.progress || 0} →{" "}
    {syncConfig.prioritizeAniListProgress
    ? userEntry?.progress &&
    userEntry.progress > 0
    ? (kenmei.chapters_read ||
    0) > userEntry.progress
    ? kenmei.chapters_read ||
    0
    : userEntry.progress
    : kenmei.chapters_read || 0
    : kenmei.chapters_read ||
    0}{" "}
    ch
    </Badge>
    )}

    {scoreWillChange && (
    <Badge
    variant="outline"
    className="border-amber-400 px-1 py-0 text-[10px]"
    >
    {userEntry?.score || 0} →{" "}
    {kenmei.score || 0}/10
    </Badge>
    )}

    {userEntry
    ? syncConfig.setPrivate &&
    !userEntry.private && (
    <Badge
    variant="outline"
    className="border-purple-400 px-1 py-0 text-[10px]"
    >
    {userEntry.private
    ? "Yes"
    : "No"}
    </Badge>
    )
    : syncConfig.setPrivate && (
    <Badge
    variant="outline"
    className="border-purple-400 px-1 py-0 text-[10px]"
    >
    {userEntry ? "Yes" : "No"}
    </Badge>
    )}

    {changeCount === 0 && (
    <span className="text-muted-foreground px-1 text-[10px]">
    No Changes
    </span>
    )}
    </>
    )}

    {isNewEntry && (
    <span className="text-[10px] font-medium text-emerald-600 dark:text-emerald-400">
    Adding to Library
    </span>
    )}

    {isCompleted && (
    <span className="text-[10px] font-medium text-amber-600 dark:text-amber-400">
    Preserving Completed
    </span>
    )}
    </div>
    </div>
    </motion.div>
    );
    })}
    </AnimatePresence>

    {/* Load more button for compact view */}
    {sortedMangaMatches.length > 0 && (
    <div className="bg-muted/20 py-3 text-center">
    {sortedMangaMatches.length > visibleItems ? (
    <Button
    onClick={() => {
    setIsLoadingMore(true);
    const newValue = Math.min(
    visibleItems + 20,
    sortedMangaMatches.length,
    );
    console.log(
    `Loading more items: ${visibleItems} → ${newValue}`,
    );

    // Add a small delay to show the loading spinner
    setTimeout(() => {
    setVisibleItems(newValue);
    setIsLoadingMore(false);
    }, 300);
    }}
    variant="outline"
    size="sm"
    className="gap-2"
    disabled={isLoadingMore}
    >
    {isLoadingMore && (
    <div className="text-primary inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"></div>
    )}
    {isLoadingMore
    ? "Loading..."
    : `Load More (${visibleItems} of ${sortedMangaMatches.length})`}
    </Button>
    ) : (
    <span className="text-muted-foreground text-xs">
    All items loaded
    </span>
    )}
    </div>
    )}
    </motion.div>
    )}
    </AnimatePresence>
    </div>
    </CardContent>
    <CardFooter className="flex justify-between">
    <Button variant="outline" onClick={handleCancel}>
    Cancel
    </Button>
    <Button
    onClick={handleStartSync}
    disabled={entriesWithChanges.length === 0 || libraryLoading}
    className="relative"
    >
    Sync
    </Button>
    </CardFooter>
    </Card>
    </motion.div>
    </motion.div>
    );

    case "sync":
    return (
    <motion.div
    variants={pageVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    >
    <SyncManager
    entries={entriesWithChanges}
    token={token || ""}
    onComplete={handleSyncComplete}
    onCancel={handleCancel}
    autoStart={false}
    syncState={state}
    syncActions={{
    ...actions,
    startSync: (entries, token, _unused, displayOrderMediaIds) =>
    actions.startSync(
    entries,
    token,
    _unused,
    displayOrderMediaIds,
    ),
    }}
    incrementalSync={syncConfig.incrementalSync}
    onIncrementalSyncChange={(value) => {
    const newConfig = { ...syncConfig, incrementalSync: value };
    setSyncConfig(newConfig);
    saveSyncConfig(newConfig);
    }}
    displayOrderMediaIds={entriesWithChanges
    .filter(Boolean)
    .map((e) => e.mediaId)}
    />
    </motion.div>
    );

    case "results": {
    if (state.report || wasCancelled) {
    return (
    <motion.div
    variants={pageVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    >
    {state.report ? (
    <SyncResultsView
    report={state.report}
    onClose={handleGoHome}
    onExportErrors={() =>
    state.report && exportSyncErrorLog(state.report)
    }
    />
    ) : (
    <div className="flex min-h-[300px] flex-col items-center justify-center">
    <div className="mb-4">
    <Loader2 className="h-10 w-10 animate-spin text-blue-500" />
    </div>
    <div className="text-lg font-medium text-blue-700 dark:text-blue-300">
    Loading synchronization results...
    </div>
    </div>
    )}
    <div className="mt-6 flex justify-center gap-4">
    <Button onClick={handleGoHome} variant="default">
    Go Home
    </Button>
    <Button onClick={handleBackToReview} variant="outline">
    Back to Sync Review
    </Button>
    </div>
    {wasCancelled && (
    <div className="mt-4 text-center text-amber-600 dark:text-amber-400">
    Synchronization was cancelled. No further entries will be
    processed.
    </div>
    )}
    </motion.div>
    );
    } else {
    return (
    <motion.div
    variants={pageVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    >
    <Card className="mx-auto w-full max-w-md p-6 text-center">
    <CardContent>
    <AlertCircle className="mx-auto mb-4 h-12 w-12 text-red-500" />
    <h3 className="text-lg font-medium">Synchronization Error</h3>
    <p className="mt-2 text-sm text-slate-500">
    {state.error ||
    "An unknown error occurred during synchronization."}
    </p>
    </CardContent>
    <CardFooter className="justify-center gap-4">
    <Button onClick={handleGoHome}>Go Home</Button>
    <Button onClick={handleBackToReview} variant="outline">
    Back to Sync Review
    </Button>
    </CardFooter>
    </Card>
    </motion.div>
    );
    }
    }
    }
    };

    return (
    <motion.div
    className="container py-6"
    initial="hidden"
    animate="visible"
    variants={pageVariants}
    >
    <AnimatePresence mode="wait">{renderContent()}</AnimatePresence>
    </motion.div>
    );
    }