'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * Entry detail drawer — shows a single submission rendered against the schema
 * version it was captured with, plus sender, attribution, and per-entry
 * actions (star, archive, mark unread, delete). Opening an unread entry marks
 * it read. Token-only styling; built on the shared `Drawer`.
 */
import { useCallback, useEffect, useState } from 'react';
import { Archive, ArchiveRestore, Loader2, Mail, Star, Trash2 } from 'lucide-react';
import { toast } from 'sonner';
import { deleteEntry, fetchEntry, updateEntry, } from '../../lib/forms-service.js';
import { emitFormsChanged } from '../../lib/forms-events.js';
import { ConfirmDialog } from '../ui/ConfirmDialog.js';
import { Drawer } from './Drawer.js';
import { FormsErrorState, btnGhostIcon } from './primitives.js';
function formatDateTime(iso) {
    if (!iso)
        return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime()))
        return '—';
    return d.toLocaleString(undefined, {
        month: 'short',
        day: 'numeric',
        year: 'numeric',
        hour: 'numeric',
        minute: '2-digit',
    });
}
/** Render a stored value for display, coping with arrays/objects/booleans. */
function displayValue(value) {
    if (value == null || value === '')
        return '—';
    if (typeof value === 'boolean')
        return value ? 'Yes' : 'No';
    if (Array.isArray(value))
        return value.map((v) => String(v)).join(', ');
    if (typeof value === 'object')
        return JSON.stringify(value);
    return String(value);
}
function attributionRows(entry) {
    return [
        { label: 'Source', value: entry.utmSource },
        { label: 'Medium', value: entry.utmMedium },
        { label: 'Campaign', value: entry.utmCampaign },
        { label: 'Page', value: entry.pageUrl },
        { label: 'Referrer', value: entry.referrer },
    ].filter((r) => r.value);
}
export function EntryDetailDrawer({ entryId, open, onOpenChange, onChanged, onDeleted, }) {
    const [detail, setDetail] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [busy, setBusy] = useState(false);
    const [confirmDelete, setConfirmDelete] = useState(false);
    const notifyChanged = useCallback(() => {
        emitFormsChanged();
        onChanged?.();
    }, [onChanged]);
    // Load the entry (and its schema) when the drawer opens, marking it read.
    useEffect(() => {
        if (!open || !entryId)
            return;
        let cancelled = false;
        setLoading(true);
        setError(null);
        setDetail(null);
        void (async () => {
            try {
                const data = await fetchEntry(entryId);
                if (cancelled)
                    return;
                if (!data) {
                    setError('Entry not found');
                    return;
                }
                setDetail(data);
                // Mark read on open (fire-and-forget; refresh the list counts).
                if (data.entry.unread) {
                    const res = await updateEntry(entryId, { unread: false });
                    if (!cancelled && !res.error)
                        notifyChanged();
                }
            }
            catch (e) {
                if (!cancelled)
                    setError(e instanceof Error ? e.message : 'Failed to load entry');
            }
            finally {
                if (!cancelled)
                    setLoading(false);
            }
        })();
        return () => {
            cancelled = true;
        };
    }, [open, entryId, notifyChanged]);
    const mutate = useCallback(async (patch) => {
        if (!entryId)
            return;
        setBusy(true);
        const res = await updateEntry(entryId, patch);
        setBusy(false);
        if (res.error) {
            toast.error(res.error);
            return;
        }
        setDetail((cur) => (cur ? { ...cur, entry: { ...cur.entry, ...patch } } : cur));
        notifyChanged();
    }, [entryId, notifyChanged]);
    const handleDelete = useCallback(async () => {
        if (!entryId)
            return;
        setBusy(true);
        const res = await deleteEntry(entryId);
        setBusy(false);
        if (res.error) {
            toast.error(res.error);
            return;
        }
        toast.success('Submission deleted');
        notifyChanged();
        onDeleted?.(entryId);
        onOpenChange(false);
    }, [entryId, notifyChanged, onDeleted, onOpenChange]);
    const entry = detail?.entry;
    const senderName = entry?.senderName || 'Anonymous';
    const attrRows = entry ? attributionRows(entry) : [];
    return (_jsxs(_Fragment, { children: [_jsx(Drawer, { open: open, onOpenChange: onOpenChange, title: entry ? `Entry${entry.entryNumber ? ` #${entry.entryNumber}` : ''}` : 'Entry', description: entry ? formatDateTime(entry.submittedAt) : undefined, headerExtra: entry ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: btnGhostIcon, "aria-pressed": entry.starred, "aria-label": entry.starred ? 'Unstar entry' : 'Star entry', disabled: busy, onClick: () => void mutate({ starred: !entry.starred }), children: _jsx(Star, { size: 18, "aria-hidden": true, className: entry.starred ? 'fill-warning text-warning' : '' }) }), _jsx("button", { type: "button", className: btnGhostIcon, "aria-pressed": entry.archived, "aria-label": entry.archived ? 'Unarchive entry' : 'Archive entry', disabled: busy, onClick: () => void mutate({ archived: !entry.archived }), children: entry.archived ? (_jsx(ArchiveRestore, { size: 18, "aria-hidden": true })) : (_jsx(Archive, { size: 18, "aria-hidden": true })) })] })) : undefined, footer: entry ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "text-destructive hover:bg-destructive/10 focus-visible:ring-ring inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:opacity-60", disabled: busy, onClick: () => setConfirmDelete(true), children: [_jsx(Trash2, { size: 16, "aria-hidden": true }), "Delete"] }), _jsxs("button", { type: "button", className: "border-border text-foreground hover:bg-accent focus-visible:ring-ring inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:opacity-60", disabled: busy, onClick: () => void mutate({ unread: !entry.unread }), children: [_jsx(Mail, { size: 16, "aria-hidden": true }), "Mark ", entry.unread ? 'read' : 'unread'] })] })) : undefined, children: loading ? (_jsxs("div", { className: "flex h-40 items-center justify-center", role: "status", "aria-live": "polite", children: [_jsx(Loader2, { className: "text-muted-foreground h-5 w-5 animate-spin", "aria-hidden": true }), _jsx("span", { className: "sr-only", children: "Loading entry\u2026" })] })) : error ? (_jsx(FormsErrorState, { message: error })) : entry ? (_jsxs("div", { className: "space-y-6", children: [_jsxs("section", { className: "space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: senderName }), entry.senderEmail && (_jsx("a", { href: `mailto:${entry.senderEmail}`, className: "text-primary block text-sm hover:underline", children: entry.senderEmail })), entry.senderPhone && (_jsx("span", { className: "text-muted-foreground block text-sm", children: entry.senderPhone }))] }), _jsx(FieldValues, { entry: entry, fields: detail.fields }), attrRows.length > 0 && (_jsxs("section", { children: [_jsx("h4", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase", children: "Attribution" }), _jsx("dl", { className: "divide-border divide-y text-sm", children: attrRows.map((row) => (_jsxs("div", { className: "flex justify-between gap-4 py-1.5", children: [_jsx("dt", { className: "text-muted-foreground shrink-0", children: row.label }), _jsx("dd", { className: "text-foreground min-w-0 truncate text-right", children: row.value })] }, row.label))) })] }))] })) : null }), _jsx(ConfirmDialog, { open: confirmDelete, onClose: () => setConfirmDelete(false), onConfirm: () => void handleDelete(), title: "Delete submission?", description: "This permanently removes the submission and any attached files. This cannot be undone.", confirmLabel: "Delete", destructive: true })] }));
}
/** Render the captured field values against the entry's schema. */
function FieldValues({ entry, fields }) {
    // Prefer the schema order; fall back to whatever keys exist on the data.
    const inputFields = fields.filter((f) => f.type !== 'divider' && f.type !== 'richtext' && f.type !== 'honeypot');
    const rows = inputFields.length
        ? inputFields.map((f) => ({ key: f.key, label: f.label }))
        : Object.keys(entry.data ?? {}).map((k) => ({ key: k, label: k }));
    if (rows.length === 0) {
        return _jsx("p", { className: "text-muted-foreground text-sm", children: "No field data captured." });
    }
    return (_jsxs("section", { children: [_jsx("h4", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase", children: "Submission" }), _jsx("dl", { className: "space-y-3", children: rows.map((row) => (_jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground text-xs", children: row.label }), _jsx("dd", { className: "text-foreground mt-0.5 text-sm wrap-break-word whitespace-pre-wrap", children: displayValue(entry.data?.[row.key]) })] }, row.key))) })] }));
}
//# sourceMappingURL=EntryDetailDrawer.js.map