'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Forms list — manage forms and view high-level submission status. Matches the
 * Forms list screenshot: summary chips, search + status filter pills, and a
 * compact table (Form / Fields / Status / Entries / Last Entry / Notify /
 * Schema). All data flows through `lib/forms-service.ts`; the Schema action
 * opens the inline `FormSchemaPane` beside the table (design's 390px schema
 * panel — previously an overlay drawer).
 */
import { ChevronRight, ClipboardList, Plus, Search, Settings2 } from 'lucide-react';
import { Toggle } from '../components/ui/Toggle.js';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { sortByRelevance } from '../lib/search.js';
import { fetchForms, fetchFormStats, setNotifyEnabled, } from '../lib/forms-service.js';
import { emitFormsChanged, onFormsChanged } from '../lib/forms-events.js';
import { InspectorPane, SplitPaneLayout, SplitPaneList } from '../components/ui/InspectorPane.js';
import { FormSchemaPane } from '../components/forms/FormSchemaPane.js';
import { FieldTypeBadge, FormStatusBadge, FormsEmptyState, FormsErrorState, FormsLoading, FormsPagination, SummaryChip, UnreadBadge, btnPrimary, } from '../components/forms/primitives.js';
const PAGE_SIZE = 10;
const FILTERS = [
    { id: 'all', label: 'All' },
    { id: 'active', label: 'Active' },
    { id: 'draft', label: 'Draft' },
    { id: 'archived', label: 'Archived' },
];
function formatRelative(iso) {
    if (!iso)
        return '—';
    const then = new Date(iso).getTime();
    if (Number.isNaN(then))
        return '—';
    const diff = Date.now() - then;
    const mins = Math.round(diff / 60000);
    if (mins < 1)
        return 'just now';
    if (mins < 60)
        return `${mins} min ago`;
    const hrs = Math.round(mins / 60);
    if (hrs < 24)
        return `${hrs} hour${hrs === 1 ? '' : 's'} ago`;
    const days = Math.round(hrs / 24);
    if (days < 7)
        return `${days} day${days === 1 ? '' : 's'} ago`;
    return new Date(iso).toLocaleDateString(undefined, {
        month: 'short',
        day: 'numeric',
        year: 'numeric',
    });
}
export function Forms({ onNavigate }) {
    const [forms, setForms] = useState([]);
    const [stats, setStats] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [search, setSearch] = useState('');
    const [filter, setFilter] = useState('all');
    const [page, setPage] = useState(1);
    // Form whose schema pane is open. Derived against `forms` so a list refetch
    // (e.g. after saving) keeps the pane's header data fresh.
    const [schemaFormId, setSchemaFormId] = useState(null);
    const load = useCallback(async () => {
        setLoading(true);
        setError(null);
        try {
            const [formsData, statsData] = await Promise.all([fetchForms(), fetchFormStats()]);
            setForms(formsData);
            setStats(statsData);
        }
        catch (e) {
            setError(e instanceof Error ? e.message : 'Failed to load forms');
        }
        finally {
            setLoading(false);
        }
    }, []);
    useEffect(() => {
        void load();
    }, [load]);
    // Refresh when another surface signals a forms/submission change.
    useEffect(() => onFormsChanged(() => void load()), [load]);
    const filtered = useMemo(() => {
        let results = forms;
        if (filter !== 'all')
            results = results.filter((f) => f.status === filter);
        const q = search.trim().toLowerCase();
        if (q) {
            results = results.filter((f) => f.name.toLowerCase().includes(q) ||
                f.slug.toLowerCase().includes(q) ||
                (f.description ?? '').toLowerCase().includes(q) ||
                f.fields.some((field) => field.label.toLowerCase().includes(q) || field.type.toLowerCase().includes(q)));
            results = sortByRelevance(results, search, (f) => [
                f.name,
                f.slug,
                f.description ?? '',
                ...f.fields.map((field) => field.label),
            ]);
        }
        return results;
    }, [forms, filter, search]);
    const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
    // Keep the page in range when the filtered set shrinks (filters, refresh).
    useEffect(() => {
        if (page > totalPages)
            setPage(totalPages);
    }, [page, totalPages]);
    const paged = useMemo(() => filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE), [filtered, page]);
    const schemaForm = useMemo(() => (schemaFormId ? (forms.find((f) => f.id === schemaFormId) ?? null) : null), [forms, schemaFormId]);
    const toggleSchema = useCallback((form) => {
        setSchemaFormId((prev) => (prev === form.id ? null : form.id));
    }, []);
    const handleNotifyToggle = useCallback(async (form, next) => {
        // Optimistic update; roll back on error.
        setForms((cur) => cur.map((f) => (f.id === form.id ? { ...f, notifyEnabled: next } : f)));
        const res = await setNotifyEnabled(form.id, next);
        if (res.error) {
            setForms((cur) => cur.map((f) => (f.id === form.id ? { ...f, notifyEnabled: !next } : f)));
            toast.error(res.error);
            return;
        }
        emitFormsChanged();
    }, []);
    return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsxs("div", { className: "space-y-5 p-6 pb-4", children: [_jsxs("header", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-[var(--txt)]", children: "Forms" }), _jsx("p", { className: "mt-1 text-sm text-[var(--sub)]", children: "Manage forms and view incoming submissions" })] }), _jsxs("button", { className: btnPrimary, onClick: () => onNavigate?.('/forms/new'), children: [_jsx(Plus, { className: "h-4 w-4", "aria-hidden": true }), "New Form"] })] }), stats && (_jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(SummaryChip, { value: stats.totalForms, label: stats.totalForms === 1 ? 'form' : 'forms' }), _jsx(SummaryChip, { value: stats.activeForms, label: "active", tone: "success" }), _jsx(SummaryChip, { value: stats.totalEntries, label: "total entries" }), _jsx(SummaryChip, { value: stats.unreadEntries, label: "unread", tone: stats.unreadEntries > 0 ? 'destructive' : 'neutral' })] })), _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "relative w-full sm:max-w-xs", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-[var(--sub)]", "aria-hidden": true }), _jsx("input", { type: "search", placeholder: "Search forms\u2026", value: search, onChange: (e) => {
                                            setSearch(e.target.value);
                                            setPage(1);
                                        }, "aria-label": "Search forms", className: "bg-input-background w-full rounded-lg border border-[var(--bdr)] py-2 pr-3 pl-9 text-sm text-[var(--txt)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none" })] }), _jsx("div", { className: "flex gap-1", role: "group", "aria-label": "Filter by status", children: FILTERS.map((f) => (_jsx("button", { type: "button", onClick: () => {
                                        setFilter(f.id);
                                        setPage(1);
                                    }, "aria-pressed": filter === f.id, className: `rounded-full px-3 py-1.5 text-sm font-medium transition-colors ${filter === f.id
                                        ? 'bg-primary text-primary-foreground'
                                        : 'text-[var(--sub)] hover:bg-[var(--acc-l)] hover:text-[var(--txt)]'}`, children: f.label }, f.id))) })] })] }), _jsxs(SplitPaneLayout, { children: [_jsx(SplitPaneList, { className: "px-6 pb-6", children: error ? (_jsx(FormsErrorState, { message: error, onRetry: load })) : loading ? (_jsx(FormsLoading, { label: "Loading forms\u2026" })) : forms.length === 0 ? (_jsx(FormsEmptyState, { icon: _jsx(ClipboardList, { className: "h-6 w-6", "aria-hidden": true }), title: "No forms yet", description: "Create your first form to start collecting submissions.", action: _jsxs("button", { className: btnPrimary, onClick: () => onNavigate?.('/forms/new'), children: [_jsx(Plus, { className: "h-4 w-4", "aria-hidden": true }), "Create New Form"] }) })) : filtered.length === 0 ? (_jsx(FormsEmptyState, { title: "No forms match your filters", description: "Try a different search term or status filter.", action: _jsx("button", { type: "button", onClick: () => {
                                    setSearch('');
                                    setFilter('all');
                                    setPage(1);
                                }, className: "text-primary text-sm font-medium hover:underline", children: "Clear filters" }) })) : (_jsx(FormsTable, { forms: paged, selectedId: schemaFormId, onOpenForm: (id) => onNavigate?.(`/forms/${id}/edit`), onOpenEntries: (id) => onNavigate?.(`/forms/${id}/submissions`), onOpenSchema: toggleSchema, onNotifyToggle: handleNotifyToggle, footer: _jsx(FormsPagination, { page: page, pageSize: PAGE_SIZE, total: filtered.length, onPageChange: setPage, noun: "form", label: "Forms pagination" }) })) }), _jsx(InspectorPane, { open: schemaForm !== null, width: 390, "aria-label": "Form schema", children: schemaForm && (_jsx(FormSchemaPane, { form: schemaForm, onClose: () => setSchemaFormId(null), onSaved: load }, schemaForm.id)) })] })] }));
}
function FormsTable({ forms, selectedId, onOpenForm, onOpenEntries, onOpenSchema, onNotifyToggle, footer, }) {
    return (_jsxs("div", { className: "rounded-lg border border-[var(--bdr)] bg-[var(--card)]", children: [_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full min-w-[760px] text-sm", "aria-label": "Forms", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-[var(--bdr)] text-left text-xs text-[var(--sub)]", children: [_jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Form" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Fields" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Status" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Entries" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Last Entry" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 text-center font-medium", children: "Notify" }), _jsx("th", { scope: "col", className: "px-4 py-2.5 text-right font-medium", children: _jsx("span", { className: "sr-only", children: "Schema" }) })] }) }), _jsx("tbody", { children: forms.map((form) => {
                                const fieldCount = form.fieldCount ?? form.fields.length;
                                const unread = form.unreadEntries ?? 0;
                                const muted = form.status === 'archived';
                                const isSelected = form.id === selectedId;
                                return (_jsxs("tr", { className: `border-b border-[var(--bdr)] transition-colors last:border-b-0 ${isSelected ? 'bg-[var(--acc-l)]' : 'hover:bg-[var(--acc-l)]'} ${muted ? 'opacity-60' : ''}`, children: [_jsx("td", { className: "px-4 py-3", children: _jsxs("button", { type: "button", onClick: () => onOpenForm(form.id), className: "block max-w-xs text-left", children: [_jsx("span", { className: "block truncate font-medium text-[var(--txt)] hover:underline", children: form.name }), _jsxs("span", { className: "block truncate text-xs text-[var(--sub)]", children: ["/", form.slug, form.description ? ` · ${form.description}` : ''] })] }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex flex-wrap items-center gap-1", children: [form.fields.slice(0, 4).map((field) => (_jsx(FieldTypeBadge, { type: field.type }, field.id))), _jsxs("span", { className: "text-xs text-[var(--sub)]", children: [fieldCount, " fields"] })] }) }), _jsx("td", { className: "px-4 py-3", children: _jsx(FormStatusBadge, { status: form.status }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("button", { type: "button", onClick: () => onOpenEntries(form.id), className: "inline-flex items-center gap-1.5 rounded font-medium text-[var(--txt)] tabular-nums hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none", "aria-label": `View ${form.totalEntries ?? 0} entries for ${form.name}`, children: [form.totalEntries ?? 0, _jsx(UnreadBadge, { count: unread }), _jsx(ChevronRight, { className: "h-3.5 w-3.5 text-[var(--sub)]", "aria-hidden": true })] }) }), _jsx("td", { className: "px-4 py-3 whitespace-nowrap text-[var(--sub)]", children: formatRelative(form.lastEntryAt) }), _jsx("td", { className: "px-4 py-3 text-center", children: _jsx(Toggle, { checked: form.notifyEnabled ?? false, onCheckedChange: (v) => onNotifyToggle(form, v), "aria-label": `Notifications for ${form.name}`, variant: "enabled" }) }), _jsx("td", { className: "px-4 py-3 text-right", children: _jsxs("button", { type: "button", onClick: () => onOpenSchema(form), "aria-expanded": isSelected, className: "inline-flex items-center gap-1.5 rounded-md border border-[var(--bdr)] px-2.5 py-1.5 text-xs font-medium text-[var(--txt)] transition-colors hover:bg-[var(--acc-l)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none", children: [_jsx(Settings2, { className: "h-3.5 w-3.5", "aria-hidden": true }), "Schema"] }) })] }, form.id));
                            }) })] }) }), footer] }));
}
//# sourceMappingURL=Forms.js.map