'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useCallback, useEffect, useRef, useState } from 'react';
import { Command } from 'cmdk';
import { Search, FileText, File, Image, Settings, LayoutDashboard, Plus, Users, ArrowRightLeft, ClipboardList, Upload, BarChart3, Clock, Maximize2, Minimize2, Sparkles, SpellCheck, Wand2, } from 'lucide-react';
import { toast } from 'sonner';
import { cmsApi } from '../lib/api.js';
import { coauthorActionDescription, coauthorActionLabel, coauthorText, } from '../lib/coauthor-client.js';
import { isAiSlashCommandInput, orderedAiActions, parseAiSlashCommand, } from '../lib/slash-command.js';
import { getActiveEditor } from '../lib/active-editor.js';
import { CoauthorResultPopover } from './CoauthorResultPopover.js';
const RECENT_ITEMS_KEY = 'actuate-recent-items';
const MAX_RECENT_ITEMS = 5;
function loadRecentItems() {
    try {
        const raw = localStorage.getItem(RECENT_ITEMS_KEY);
        return raw ? JSON.parse(raw) : [];
    }
    catch {
        return [];
    }
}
function saveRecentItem(item) {
    try {
        const items = loadRecentItems().filter((i) => i.id !== item.id);
        items.unshift(item);
        localStorage.setItem(RECENT_ITEMS_KEY, JSON.stringify(items.slice(0, MAX_RECENT_ITEMS)));
    }
    catch {
        /* localStorage unavailable */
    }
}
const staticActions = [
    { id: 'action-new-page', label: 'Create new page', icon: Plus, action: '/pages/new' },
    { id: 'action-new-post', label: 'Create new post', icon: Plus, action: '/posts/new' },
    { id: 'action-upload-media', label: 'Upload media', icon: Upload, action: '/media?upload=true' },
    { id: 'action-view-seo', label: 'View SEO', icon: BarChart3, action: '/seo' },
    { id: 'action-open-settings', label: 'Open settings', icon: Settings, action: '/settings' },
];
const AI_ACTION_ICONS = {
    rewrite: Wand2,
    expand: Maximize2,
    compress: Minimize2,
    proofread: SpellCheck,
};
const INITIAL_AI_RESULT = {
    open: false,
    loading: false,
    action: 'rewrite',
    before: '',
    after: '',
    target: null,
};
function truncatePreview(text, max = 60) {
    if (text.length <= max)
        return text;
    return `${text.slice(0, max - 1)}…`;
}
const navigationCommands = [
    { id: 'nav-dashboard', label: 'Dashboard', icon: LayoutDashboard, action: '/' },
    { id: 'nav-posts', label: 'Posts', icon: FileText, action: '/posts' },
    { id: 'nav-pages', label: 'Pages', icon: File, action: '/pages' },
    { id: 'nav-media', label: 'Media', icon: Image, action: '/media' },
    { id: 'nav-forms', label: 'Forms', icon: ClipboardList, action: '/forms' },
    { id: 'nav-redirects', label: 'Redirects', icon: ArrowRightLeft, action: '/redirects' },
    { id: 'nav-users', label: 'Users', icon: Users, action: '/users' },
    { id: 'nav-settings', label: 'Settings', icon: Settings, action: '/settings' },
];
export function CommandPalette({ open, onOpenChange, onNavigate }) {
    const [search, setSearch] = useState('');
    const [documents, setDocuments] = useState([]);
    const [media, setMedia] = useState([]);
    const [users, setUsers] = useState([]);
    const [recentItems, setRecentItems] = useState([]);
    const [loading, setLoading] = useState(false);
    const [aiResult, setAiResult] = useState(INITIAL_AI_RESULT);
    const debounceRef = useRef(undefined);
    useEffect(() => {
        const down = (e) => {
            if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
                e.preventDefault();
                onOpenChange(!open);
            }
        };
        document.addEventListener('keydown', down);
        return () => document.removeEventListener('keydown', down);
    }, [open, onOpenChange]);
    useEffect(() => {
        if (open) {
            setRecentItems(loadRecentItems());
        }
    }, [open]);
    const fetchResults = useCallback(async (query) => {
        if (!query.trim()) {
            setDocuments([]);
            setMedia([]);
            setUsers([]);
            return;
        }
        setLoading(true);
        try {
            const res = await cmsApi(`/search/global?q=${encodeURIComponent(query)}`);
            if (res.data) {
                setDocuments(res.data.documents ?? []);
                setMedia(res.data.media ?? []);
                setUsers(res.data.users ?? []);
            }
        }
        catch {
            setDocuments([]);
            setMedia([]);
            setUsers([]);
        }
        finally {
            setLoading(false);
        }
    }, []);
    useEffect(() => {
        if (debounceRef.current)
            clearTimeout(debounceRef.current);
        if (!search.trim() || isAiSlashCommandInput(search)) {
            setDocuments([]);
            setMedia([]);
            setUsers([]);
            return;
        }
        debounceRef.current = setTimeout(() => fetchResults(search), 250);
        return () => {
            if (debounceRef.current)
                clearTimeout(debounceRef.current);
        };
    }, [search, fetchResults]);
    const handleSelect = (action, recent) => {
        if (recent) {
            saveRecentItem(recent);
        }
        onNavigate(action);
        onOpenChange(false);
        setSearch('');
    };
    const runSlashAction = useCallback(async (action, text) => {
        if (!text.trim()) {
            toast.message(`Provide text after the command: /ai ${action} <your text>`);
            return;
        }
        const target = getActiveEditor();
        onOpenChange(false);
        setSearch('');
        setAiResult({
            open: true,
            loading: true,
            action,
            before: text,
            after: '',
            target,
        });
        const outcome = await coauthorText(action, text);
        if (!outcome.ok) {
            setAiResult((prev) => ({ ...prev, loading: false, error: outcome.error }));
            toast.error(outcome.error);
            return;
        }
        setAiResult((prev) => ({
            ...prev,
            loading: false,
            after: outcome.result.text,
            changes: outcome.result.changes,
            error: undefined,
        }));
    }, [onOpenChange]);
    const handleAiApply = useCallback(() => {
        const { target, after, action } = aiResult;
        if (!target) {
            void navigator.clipboard
                ?.writeText(after)
                .then(() => toast.success('Copied to clipboard.'))
                .catch(() => toast.error('Clipboard unavailable — copy manually.'));
            setAiResult(INITIAL_AI_RESULT);
            return;
        }
        const { from, to, empty } = target.state.selection;
        const chain = target.chain().focus();
        if (!empty) {
            chain.insertContentAt({ from, to }, after).run();
        }
        else {
            chain.insertContent(after).run();
        }
        toast.success(`${coauthorActionLabel(action)} applied.`);
        setAiResult(INITIAL_AI_RESULT);
    }, [aiResult]);
    const handleAiCopy = useCallback(async () => {
        try {
            await navigator.clipboard.writeText(aiResult.after);
            toast.success('Copied to clipboard.');
        }
        catch {
            toast.error('Clipboard unavailable — copy manually.');
        }
    }, [aiResult.after]);
    const handleAiDiscard = useCallback(() => {
        setAiResult(INITIAL_AI_RESULT);
    }, []);
    const hasQuery = search.trim().length > 0;
    const hasResults = documents.length > 0 || media.length > 0 || users.length > 0;
    const isAiMode = isAiSlashCommandInput(search);
    const aiCommand = parseAiSlashCommand(search);
    const aiPayload = aiCommand?.text ?? '';
    const aiActions = orderedAiActions(search);
    const popover = (_jsx(CoauthorResultPopover, { open: aiResult.open, loading: aiResult.loading, action: aiResult.action, before: aiResult.before, after: aiResult.after, error: aiResult.error, changes: aiResult.changes, applyLabel: aiResult.target ? 'Apply to editor' : 'Copy to clipboard', onApply: handleAiApply, onCopy: handleAiCopy, onDiscard: handleAiDiscard }));
    if (!open)
        return popover;
    return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-50 flex items-start justify-center bg-black/50 px-4 pt-[20vh]", onClick: () => {
                    onOpenChange(false);
                    setSearch('');
                }, role: "presentation", children: _jsx("div", { role: "dialog", "aria-modal": "true", className: "w-full max-w-2xl", onClick: (e) => e.stopPropagation(), children: _jsxs(Command, { className: "bg-card w-full overflow-hidden rounded-lg shadow-2xl", onKeyDown: (e) => {
                            if (e.key === 'Escape') {
                                onOpenChange(false);
                                setSearch('');
                            }
                        }, shouldFilter: !hasQuery, children: [_jsxs("div", { className: "border-border flex items-center border-b px-4", children: [_jsx(Search, { className: "text-muted-foreground mr-3 h-5 w-5 shrink-0" }), _jsx(Command.Input, { value: search, onValueChange: setSearch, placeholder: "Search, jump to, or type /ai to use the AI co-author\u2026", className: "placeholder:text-muted-foreground w-full bg-transparent py-4 text-base focus:outline-none" }), loading && (_jsx("div", { className: "border-border mr-2 h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-t-gray-600" })), _jsx("kbd", { className: "bg-muted text-muted-foreground hidden shrink-0 rounded px-2 py-1 font-mono text-xs sm:inline-block", children: "ESC" })] }), _jsxs(Command.List, { className: "max-h-[400px] overflow-y-auto p-2", children: [_jsx(Command.Empty, { className: "text-muted-foreground py-6 text-center text-sm", children: loading ? 'Searching...' : 'No results found.' }), isAiMode && (_jsxs(Command.Group, { heading: "AI co-author", className: "px-2 py-2", children: [_jsxs("div", { className: "text-muted-foreground mb-2 flex items-center gap-1 text-xs font-medium", children: [_jsx(Sparkles, { className: "h-3 w-3", "aria-hidden": true }), " AI CO-AUTHOR"] }), aiActions.map((action) => {
                                                const Icon = AI_ACTION_ICONS[action];
                                                const isExactMatch = aiCommand?.action === action;
                                                const previewable = isExactMatch && aiPayload.length > 0;
                                                return (_jsxs(Command.Item, { value: `ai ${action}`, onSelect: () => runSlashAction(action, aiPayload), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Icon, { className: "text-primary h-4 w-4" }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsxs("span", { className: "font-medium", children: [coauthorActionLabel(action), previewable && (_jsxs("span", { className: "text-muted-foreground ml-1 font-normal", children: ["\u201C", truncatePreview(aiPayload), "\u201D"] }))] }), _jsx("span", { className: "text-muted-foreground text-xs", children: coauthorActionDescription(action) })] }), _jsxs("kbd", { className: "bg-muted text-muted-foreground ml-auto rounded px-1.5 py-0.5 font-mono text-[10px]", children: ["/ai ", action] })] }, `ai-${action}`));
                                            })] })), !isAiMode && !hasQuery && recentItems.length > 0 && (_jsxs(Command.Group, { heading: "Recent", className: "px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "RECENT" }), recentItems.map((item) => (_jsxs(Command.Item, { value: `recent ${item.label}`, onSelect: () => handleSelect(item.path, item), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Clock, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { children: item.label }), _jsx("span", { className: "text-muted-foreground ml-auto text-xs capitalize", children: item.type })] }, `recent-${item.id}`)))] })), !isAiMode && hasQuery && documents.length > 0 && (_jsxs(Command.Group, { heading: "Documents", className: "px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "DOCUMENTS" }), documents.map((doc) => (_jsxs(Command.Item, { value: doc.title ?? doc.slug ?? doc.id, onSelect: () => handleSelect(`/collections/${doc.collection}/${doc.id}`, {
                                                    id: `doc-${doc.id}`,
                                                    label: doc.title ?? doc.slug ?? doc.id,
                                                    path: `/collections/${doc.collection}/${doc.id}`,
                                                    type: 'document',
                                                }), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(FileText, { className: "text-muted-foreground h-4 w-4" }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate", children: doc.title ?? doc.slug ?? doc.id }), _jsxs("span", { className: "text-muted-foreground text-xs", children: [doc.collection, " \u00B7 ", doc.status] })] })] }, `doc-${doc.id}`)))] })), !isAiMode && hasQuery && media.length > 0 && (_jsxs(Command.Group, { heading: "Media", className: "mt-1 px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "MEDIA" }), media.map((m) => (_jsxs(Command.Item, { value: m.filename, onSelect: () => handleSelect(`/media?selected=${m.id}`, {
                                                    id: `media-${m.id}`,
                                                    label: m.filename,
                                                    path: `/media?selected=${m.id}`,
                                                    type: 'media',
                                                }), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Image, { className: "text-muted-foreground h-4 w-4" }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate", children: m.filename }), _jsx("span", { className: "text-muted-foreground text-xs", children: m.mimeType })] })] }, `media-${m.id}`)))] })), !isAiMode && hasQuery && users.length > 0 && (_jsxs(Command.Group, { heading: "Users", className: "mt-1 px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "USERS" }), users.map((u) => (_jsxs(Command.Item, { value: `${u.name} ${u.email}`, onSelect: () => handleSelect(`/users?selected=${u.id}`, {
                                                    id: `user-${u.id}`,
                                                    label: u.name,
                                                    path: `/users?selected=${u.id}`,
                                                    type: 'user',
                                                }), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Users, { className: "text-muted-foreground h-4 w-4" }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate", children: u.name }), _jsxs("span", { className: "text-muted-foreground text-xs", children: [u.email, " \u00B7 ", u.role] })] })] }, `user-${u.id}`)))] })), !isAiMode && (!hasQuery || !hasResults) && (_jsxs(Command.Group, { heading: "Navigation", className: "px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "NAVIGATION" }), navigationCommands.map((cmd) => {
                                                const Icon = cmd.icon;
                                                return (_jsxs(Command.Item, { value: cmd.label, onSelect: () => handleSelect(cmd.action), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Icon, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { children: cmd.label })] }, cmd.id));
                                            })] })), !isAiMode && (_jsxs(Command.Group, { heading: "Actions", className: "mt-2 px-2 py-2", children: [_jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium", children: "ACTIONS" }), staticActions.map((cmd) => {
                                                const Icon = cmd.icon;
                                                return (_jsxs(Command.Item, { value: cmd.label, onSelect: () => handleSelect(cmd.action, {
                                                        id: cmd.id,
                                                        label: cmd.label,
                                                        path: cmd.action,
                                                        type: 'action',
                                                    }), className: "hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2", children: [_jsx(Icon, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { children: cmd.label })] }, cmd.id));
                                            })] }))] }), _jsx("div", { className: "border-border bg-muted text-muted-foreground flex items-center justify-between border-t px-4 py-3 text-xs", children: _jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("kbd", { className: "border-border bg-card rounded border px-1.5 py-0.5 text-[10px]", children: "\u2191" }), _jsx("kbd", { className: "border-border bg-card rounded border px-1.5 py-0.5 text-[10px]", children: "\u2193" }), "to navigate"] }), _jsxs("span", { className: "flex items-center gap-1", children: [_jsx("kbd", { className: "border-border bg-card rounded border px-1.5 py-0.5 text-[10px]", children: "\u21B5" }), "to select"] })] }) })] }) }) }), popover] }));
}
//# sourceMappingURL=CommandPalette.js.map