"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { AdminCard } from "@/components/admin/AdminCard";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import InfoTooltip from "@/components/ui/info-tooltip";
import { Input } from "@/components/ui/input";
import { useTranslation } from "@/lib/i18n/client";
import { formatBytes } from "@/lib/utils";
import { useMutation, useQuery } from "@tanstack/react-query";
import { formatDistanceToNow } from "date-fns";
import {
AlertCircle,
CheckCircle2,
ChevronDown,
ChevronRight,
Clock,
Database,
ExternalLink,
FileText,
FileType,
Image as ImageIcon,
Link as LinkIcon,
Loader2,
RefreshCw,
Search,
Sparkles,
Tag,
User,
XCircle,
} from "lucide-react";
import { parseAsString, useQueryState } from "nuqs";
import { toast } from "sonner";
import { useTRPC } from "@karakeep/shared-react/trpc";
import { BookmarkTypes } from "@karakeep/shared/types/bookmarks";
export default function BookmarkDebugger() {
const api = useTRPC();
const { t } = useTranslation();
const [inputValue, setInputValue] = useState("");
const [bookmarkId, setBookmarkId] = useQueryState(
"bookmarkId",
parseAsString.withDefault(""),
);
const [showHtmlPreview, setShowHtmlPreview] = useState(false);
// Sync input value with URL on mount/change
useEffect(() => {
if (bookmarkId) {
setInputValue(bookmarkId);
}
}, [bookmarkId]);
const {
data: debugInfo,
isLoading,
error,
} = useQuery(
api.admin.getBookmarkDebugInfo.queryOptions(
{ bookmarkId: bookmarkId },
{ enabled: !!bookmarkId && bookmarkId.length > 0 },
),
);
const handleLookup = () => {
if (inputValue.trim()) {
setBookmarkId(inputValue.trim());
}
};
const recrawlMutation = useMutation(
api.admin.adminRecrawlBookmark.mutationOptions({
onSuccess: () => {
toast.success(t("admin.admin_tools.action_success"), {
description: t("admin.admin_tools.recrawl_queued"),
});
},
onError: (error) => {
toast.error(t("admin.admin_tools.action_failed"), {
description: error.message,
});
},
}),
);
const reindexMutation = useMutation(
api.admin.adminReindexBookmark.mutationOptions({
onSuccess: () => {
toast.success(t("admin.admin_tools.action_success"), {
description: t("admin.admin_tools.reindex_queued"),
});
},
onError: (error) => {
toast.error(t("admin.admin_tools.action_failed"), {
description: error.message,
});
},
}),
);
const retagMutation = useMutation(
api.admin.adminRetagBookmark.mutationOptions({
onSuccess: () => {
toast.success(t("admin.admin_tools.action_success"), {
description: t("admin.admin_tools.retag_queued"),
});
},
onError: (error) => {
toast.error(t("admin.admin_tools.action_failed"), {
description: error.message,
});
},
}),
);
const resummarizeMutation = useMutation(
api.admin.adminResummarizeBookmark.mutationOptions({
onSuccess: () => {
toast.success(t("admin.admin_tools.action_success"), {
description: t("admin.admin_tools.resummarize_queued"),
});
},
onError: (error) => {
toast.error(t("admin.admin_tools.action_failed"), {
description: error.message,
});
},
}),
);
const handleRecrawl = () => {
if (bookmarkId) {
recrawlMutation.mutate({ bookmarkId });
}
};
const handleReindex = () => {
if (bookmarkId) {
reindexMutation.mutate({ bookmarkId });
}
};
const handleRetag = () => {
if (bookmarkId) {
retagMutation.mutate({ bookmarkId });
}
};
const handleResummarize = () => {
if (bookmarkId) {
resummarizeMutation.mutate({ bookmarkId });
}
};
const getStatusBadge = (status: "pending" | "failure" | "success" | null) => {
if (!status) return null;
const config = {
success: {
variant: "default" as const,
icon: CheckCircle2,
},
failure: {
variant: "destructive" as const,
icon: XCircle,
},
pending: {
variant: "secondary" as const,
icon: AlertCircle,
},
};
const { variant, icon: Icon } = config[status];
return (
{error.message}
{debugInfo.linkInfo.htmlContentPreview}
)}