import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Loader2, Plus, Printer, ExternalLink, AlertTriangle, Info, FileText, ShieldCheck, Copy, Check, Download } from 'lucide-react';
import { multiVirtualPrinterApi, virtualPrinterApi } from '../api/client';
import { Card, CardContent } from './Card';
import { Button } from './Button';
import { Toggle } from './Toggle';
import { useToast } from '../contexts/ToastContext';
import { copyTextToClipboard, downloadTextFile } from '../utils/clipboard';
import { VirtualPrinterCard } from './VirtualPrinterCard';
import { VirtualPrinterAddDialog } from './VirtualPrinterAddDialog';
export function VirtualPrinterList() {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { showToast } = useToast();
const [showAddDialog, setShowAddDialog] = useState(false);
const { data, isLoading } = useQuery({
queryKey: ['virtual-printers'],
queryFn: multiVirtualPrinterApi.list,
refetchInterval: 10000,
});
const { data: globalSettings } = useQuery({
queryKey: ['virtual-printer-settings'],
queryFn: virtualPrinterApi.getSettings,
});
const archiveNameSourceMutation = useMutation({
mutationFn: (source: 'metadata' | 'filename') =>
virtualPrinterApi.updateSettings({ archive_name_source: source }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['virtual-printer-settings'] });
showToast(t('virtualPrinter.toast.updated'));
},
onError: (error: Error) => {
showToast(error.message || t('virtualPrinter.toast.failedToUpdate'), 'error');
},
});
const useFilename = globalSettings?.archive_name_source === 'filename';
// Shared CA certificate — the slicer imports it once to trust every VP's
// TLS connection. Generated on demand by the backend, never changes.
const { data: caCert } = useQuery({
queryKey: ['vp-ca-certificate'],
queryFn: multiVirtualPrinterApi.getCaCertificate,
staleTime: Infinity,
});
const [caCopied, setCaCopied] = useState(false);
const handleCopyCert = async () => {
if (!caCert) return;
const ok = await copyTextToClipboard(caCert.pem);
if (ok) {
setCaCopied(true);
showToast(t('virtualPrinter.caCert.copied'));
setTimeout(() => setCaCopied(false), 2000);
} else {
showToast(t('virtualPrinter.toast.copyFailed'), 'error');
}
};
const handleDownloadCert = () => {
if (!caCert) return;
downloadTextFile(caCert.pem, 'bambuddy-virtual-printer-ca.crt', 'application/x-pem-file');
};
if (isLoading) {
return (
{t('virtualPrinter.setupRequired.title')}
{t('virtualPrinter.setupRequired.description')}
{t('virtualPrinter.howItWorks.title')}
{t('virtualPrinter.caCert.title')}
{t('virtualPrinter.caCert.description')}
{caCert && ({t('virtualPrinter.caCert.fingerprint')}: {caCert.fingerprint_sha256}
)}{t('virtualPrinter.archiveNameSource.title')}
{t('virtualPrinter.archiveNameSource.description')}
{t('virtualPrinter.list.empty')}