'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useMemo, useCallback } from 'react';
import { Star, Copy, Trash2 } from 'lucide-react';
import * as SwitchPrimitive from '@radix-ui/react-switch';
import { BlockCatalog } from '@actuate-media/cms-core/page-builder';
import { AIBlockAssist } from './AIBlockAssist.js';
import { RelationshipField } from './RelationshipField.js';
import { TipTapEditor } from '../../components/TipTapEditor.js';
import { MediaPickerModal } from '../../components/MediaPickerModal.js';
const INPUT_CLASS = 'w-full px-3 py-2 text-sm bg-background border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring';
const LABEL_CLASS = 'text-sm font-medium text-foreground mb-1 block';
export function BlockEditor({ node, onUpdateBlock, onUpdateSettings, onRemoveNode, onDuplicateNode, config, }) {
    const [confirmDelete, setConfirmDelete] = useState(false);
    const catalog = useMemo(() => new BlockCatalog(), []);
    const blockDef = useMemo(() => catalog.get(node.settings.blockType), [catalog, node.settings.blockType]);
    const handleFieldChange = useCallback((fieldName, value) => {
        onUpdateBlock(node.id, { [fieldName]: value });
    }, [node.id, onUpdateBlock]);
    const handleVariantChange = useCallback((variantName) => {
        onUpdateSettings(node.id, { variant: variantName });
    }, [node.id, onUpdateSettings]);
    const handleDelete = useCallback(() => {
        if (confirmDelete) {
            onRemoveNode(node.id);
            setConfirmDelete(false);
        }
        else {
            setConfirmDelete(true);
        }
    }, [confirmDelete, node.id, onRemoveNode]);
    if (!blockDef) {
        return (_jsx("div", { className: "p-4", children: _jsxs("p", { className: "text-muted-foreground text-sm", children: ["Unknown block type: ", _jsx("code", { className: "text-xs", children: node.settings.blockType })] }) }));
    }
    return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "border-border border-b p-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Star, { size: 16, className: "text-muted-foreground" }), _jsx("span", { className: "text-foreground flex-1 text-sm font-medium", children: blockDef.label }), _jsx(AIBlockAssist, { block: node, onUpdateData: (data) => onUpdateBlock(node.id, data) })] }), blockDef.description && (_jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: blockDef.description }))] }), blockDef.variants.length > 1 && (_jsxs("div", { className: "border-border border-b p-4", children: [_jsx("p", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase", children: "Variant" }), _jsx("div", { className: "grid grid-cols-2 gap-1.5", children: blockDef.variants.map((variant) => (_jsx("button", { type: "button", onClick: () => handleVariantChange(variant.name), className: `rounded-md border px-2 py-1.5 text-xs transition-colors ${node.settings.variant === variant.name
                                ? 'bg-primary text-primary-foreground border-primary'
                                : 'bg-background border-input text-foreground hover:bg-accent'}`, children: variant.label }, variant.name))) })] })), _jsxs("div", { className: "flex-1 space-y-4 p-4", children: [_jsx("p", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase", children: "Fields" }), Object.entries(blockDef.fields).map(([fieldName, fieldDef]) => (_jsx(FieldRenderer, { name: fieldName, definition: fieldDef, value: node.data[fieldName], onChange: (value) => handleFieldChange(fieldName, value) }, fieldName)))] }), _jsxs("div", { className: "border-border space-y-2 border-t p-4", children: [_jsxs("button", { type: "button", onClick: () => onDuplicateNode(node.id), className: "bg-background border-input hover:bg-accent flex w-full items-center justify-center gap-2 rounded-md border px-3 py-2 text-sm font-medium transition-colors", children: [_jsx(Copy, { size: 14 }), "Duplicate"] }), _jsxs("button", { type: "button", onClick: handleDelete, onBlur: () => setConfirmDelete(false), className: `flex w-full items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors ${confirmDelete
                            ? 'bg-destructive text-destructive-foreground'
                            : 'bg-background border-destructive text-destructive hover:bg-destructive/10 border'}`, children: [_jsx(Trash2, { size: 14 }), confirmDelete ? 'Click again to confirm' : 'Delete'] })] })] }));
}
function FieldRenderer({ name, definition, value, onChange }) {
    const label = definition.label || name;
    switch (definition.type) {
        case 'text':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder, className: INPUT_CLASS })] }));
        case 'richText':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("div", { className: "border-input bg-background overflow-hidden rounded-md border", children: _jsx(TipTapEditor, { content: value ?? '', onChange: (html) => onChange(html), placeholder: definition.admin?.placeholder }) })] }));
        case 'url':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "url", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder ?? 'https://', className: INPUT_CLASS })] }));
        case 'number':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "number", value: value ?? '', onChange: (e) => onChange(e.target.value ? Number(e.target.value) : undefined), min: definition.min, max: definition.max, step: definition.step, className: INPUT_CLASS })] }));
        case 'boolean':
            return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-foreground text-sm font-medium", children: label }), _jsx(SwitchPrimitive.Root, { checked: !!value, onCheckedChange: (checked) => onChange(checked), className: "bg-input data-[state=checked]:bg-primary relative h-5 w-9 rounded-full transition-colors", "aria-label": label, children: _jsx(SwitchPrimitive.Thumb, { className: "bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[18px]" }) })] }));
        case 'media':
            return _jsx(MediaFieldRenderer, { label: label, value: value, onChange: onChange });
        case 'select':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("select", { value: value ?? '', onChange: (e) => onChange(e.target.value), className: INPUT_CLASS, children: [_jsx("option", { value: "", children: "Select..." }), definition.options.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] })] }));
        case 'array':
            return _jsx(ArrayFieldRenderer, { label: label, value: value, onChange: onChange });
        case 'json':
            return _jsx(JsonFieldRenderer, { label: label, value: value, onChange: onChange });
        case 'date':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "date", value: typeof value === 'string' && value ? value.slice(0, 10) : '', onChange: (e) => onChange(e.target.value || undefined), className: INPUT_CLASS })] }));
        case 'slug':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => {
                            const slug = e.target.value
                                .toLowerCase()
                                .replace(/[^a-z0-9-]+/g, '-')
                                .replace(/^-+|-+$/g, '');
                            onChange(slug);
                        }, placeholder: definition.admin?.placeholder ?? 'page-slug', className: INPUT_CLASS })] }));
        case 'relationship':
            return (_jsx(RelationshipField, { definition: definition, value: value, onChange: onChange, label: label }));
        case 'email':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "email", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder ?? 'email@example.com', className: INPUT_CLASS })] }));
        case 'color':
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "color", value: value ?? '#000000', onChange: (e) => onChange(e.target.value), className: "border-input h-9 w-9 cursor-pointer rounded-md border" }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: "#000000", className: `${INPUT_CLASS} flex-1` })] })] }));
        default:
            return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: String(value ?? ''), onChange: (e) => onChange(e.target.value), className: INPUT_CLASS })] }));
    }
}
/**
 * Block-level media picker. Wires the cross-cutting MediaPickerModal so
 * custom blocks declared with `type: 'media'` actually get a working
 * browse-and-select flow instead of a free-text input.
 */
function MediaFieldRenderer({ label, value, onChange }) {
    const [open, setOpen] = useState(false);
    const url = typeof value === 'string'
        ? value
        : value && typeof value === 'object' && 'url' in value
            ? String(value.url)
            : '';
    return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: url, onChange: (e) => onChange(e.target.value), placeholder: "https://...", className: `${INPUT_CLASS} flex-1` }), _jsx("button", { type: "button", onClick: () => setOpen(true), className: "bg-accent text-foreground border-input hover:bg-accent/80 rounded-md border px-3 py-2 text-xs font-medium transition-colors", children: "Browse" })] }), url && /\.(png|jpe?g|gif|webp|avif|svg)(\?|$)/i.test(url) && (_jsx("div", { className: "border-border bg-muted mt-2 overflow-hidden rounded-md border", children: _jsx("img", { src: url, alt: "", className: "bg-checkered h-32 w-full object-contain" }) })), _jsx(MediaPickerModal, { open: open, onClose: () => setOpen(false), onSelect: (selectedUrl) => {
                    onChange(selectedUrl);
                    setOpen(false);
                } })] }));
}
/**
 * JSON editor for free-form object/array fields. The textarea is the
 * source of truth while the user is typing — we only commit a parsed
 * value back upstream once the JSON is well-formed, otherwise the user
 * sees a validation error inline. This prevents typing-induced state
 * loss and keeps the UI usable for arrays of objects (a common shape
 * for custom blocks).
 */
function JsonFieldRenderer({ label, value, onChange }) {
    const initial = useMemo(() => {
        if (value === undefined || value === null)
            return '';
        try {
            return JSON.stringify(value, null, 2);
        }
        catch {
            return '';
        }
    }, [value]);
    const [draft, setDraft] = useState(initial);
    const [error, setError] = useState(null);
    const handleChange = (next) => {
        setDraft(next);
        if (next.trim() === '') {
            setError(null);
            onChange(undefined);
            return;
        }
        try {
            onChange(JSON.parse(next));
            setError(null);
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Invalid JSON');
        }
    };
    return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("textarea", { value: draft, onChange: (e) => handleChange(e.target.value), rows: 6, spellCheck: false, className: `${INPUT_CLASS} resize-y font-mono text-xs` }), error && (_jsx("p", { className: "text-destructive mt-1 text-xs", role: "alert", children: error }))] }));
}
/**
 * Lightweight array editor — supports homogenous arrays of strings or
 * objects. For block fields we deliberately keep this simple: full
 * nested-field editing belongs in the document-level FieldRenderer.
 */
function ArrayFieldRenderer({ label, value, onChange }) {
    const items = Array.isArray(value) ? value : [];
    const isObjectArray = items.length > 0 && typeof items[0] === 'object' && items[0] !== null;
    if (isObjectArray) {
        // For object arrays fall back to JSON — mirrors what most consumers
        // expect when their block declares `type: 'array'` with no schema.
        return _jsx(JsonFieldRenderer, { label: label, value: value, onChange: onChange });
    }
    const updateItem = (idx, next) => {
        const copy = [...items];
        copy[idx] = next;
        onChange(copy);
    };
    const addItem = () => onChange([...items, '']);
    const removeItem = (idx) => onChange(items.filter((_, i) => i !== idx));
    return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "space-y-2", children: [items.map((item, idx) => (_jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: typeof item === 'string' ? item : '', onChange: (e) => updateItem(idx, e.target.value), className: `${INPUT_CLASS} flex-1` }), _jsx("button", { type: "button", onClick: () => removeItem(idx), "aria-label": `Remove item ${idx + 1}`, className: "text-destructive border-input hover:bg-destructive/10 rounded-md border px-2 py-2 text-xs transition-colors", children: _jsx(Trash2, { size: 14 }) })] }, idx))), _jsx("button", { type: "button", onClick: addItem, className: "bg-accent text-foreground border-input hover:bg-accent/80 w-full rounded-md border px-3 py-2 text-xs font-medium transition-colors", children: "+ Add item" })] })] }));
}
//# sourceMappingURL=BlockEditor.js.map