'use client';
import { useState, useCallback, useRef, useMemo } from 'react';
import { addNode, removeNode, moveNode, updateNodeSettings, updateBlockData, findNode, findParent, createEmptyPage, createSection, createContainer, createRow, createColumn, createBlock, hasChildren, } from '@actuate-media/cms-core';
const MAX_HISTORY = 50;
function deepClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}
function regenerateIds(node) {
    const cloned = deepClone(node);
    let counter = 0;
    function walk(n) {
        n.id = `node_${Date.now().toString(36)}_${(counter++).toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
        if (Array.isArray(n.children)) {
            for (const child of n.children)
                walk(child);
        }
    }
    walk(cloned);
    return cloned;
}
export function useBuilderState(initialTree, initialPageSettings) {
    const [tree, setTree] = useState(() => initialTree ?? createEmptyPage());
    const [selectedNodeId, setSelectedNodeId] = useState(null);
    const [deviceMode, setDeviceMode] = useState('desktop');
    const [activeTab, setActiveTab] = useState('page');
    const [showGridOverlay, setShowGridOverlay] = useState(false);
    const [pageSettings, setPageSettingsState] = useState({
        title: '',
        slug: '',
        ...initialPageSettings,
    });
    const [dirty, setDirty] = useState(false);
    const undoStack = useRef([]);
    const redoStack = useRef([]);
    const pushHistory = useCallback((currentTree) => {
        undoStack.current = [...undoStack.current.slice(-MAX_HISTORY + 1), currentTree];
        redoStack.current = [];
    }, []);
    const [canUndo, setCanUndo] = useState(false);
    const [canRedo, setCanRedo] = useState(false);
    const applyTreeChange = useCallback((fn) => {
        setTree((prev) => {
            pushHistory(prev);
            const next = fn(prev);
            setDirty(true);
            setCanUndo(true);
            setCanRedo(false);
            return next;
        });
    }, [pushHistory]);
    const selectedNode = useMemo(() => {
        if (!selectedNodeId)
            return null;
        return findNode(tree, selectedNodeId) ?? null;
    }, [tree, selectedNodeId]);
    const selectNode = useCallback((id) => {
        setSelectedNodeId(id);
        if (id) {
            const node = findNode(tree, id);
            if (node) {
                if (node.type === 'block')
                    setActiveTab('block');
                else if (node.type === 'page')
                    setActiveTab('page');
                else
                    setActiveTab('node');
            }
        }
    }, [tree]);
    const setPageSettings = useCallback((settings) => {
        setPageSettingsState((prev) => ({ ...prev, ...settings }));
        setDirty(true);
    }, []);
    const addSection = useCallback(() => {
        applyTreeChange((prev) => {
            const section = createSection({ paddingTop: '64px', paddingBottom: '64px' });
            const container = createContainer();
            const col = createColumn(12);
            const row = createRow([col]);
            container.children = [row];
            section.children = [container];
            return addNode(prev, prev.id, section);
        });
    }, [applyTreeChange]);
    const addRowToSection = useCallback((sectionId) => {
        applyTreeChange((prev) => {
            const section = findNode(prev, sectionId);
            if (!section || !hasChildren(section))
                return prev;
            const containers = section.children.filter((c) => c.type === 'container');
            const targetId = containers.length > 0 ? containers[containers.length - 1].id : sectionId;
            const col = createColumn(12);
            const row = createRow([col]);
            return addNode(prev, targetId, row);
        });
    }, [applyTreeChange]);
    const addBlockToColumn = useCallback((columnId, blockType, variant) => {
        applyTreeChange((prev) => {
            const block = createBlock(blockType, variant);
            return addNode(prev, columnId, block);
        });
    }, [applyTreeChange]);
    const addNodeAtId = useCallback((parentId, node, index) => {
        applyTreeChange((prev) => addNode(prev, parentId, node, index));
    }, [applyTreeChange]);
    const removeNodeById = useCallback((id) => {
        applyTreeChange((prev) => {
            const result = removeNode(prev, id);
            if (selectedNodeId === id)
                setSelectedNodeId(null);
            return result;
        });
    }, [applyTreeChange, selectedNodeId]);
    const moveNodeById = useCallback((id, newParentId, index) => {
        applyTreeChange((prev) => moveNode(prev, id, newParentId, index));
    }, [applyTreeChange]);
    const updateSettings = useCallback((id, settings) => {
        applyTreeChange((prev) => updateNodeSettings(prev, id, settings));
    }, [applyTreeChange]);
    const updateBlock = useCallback((id, data) => {
        applyTreeChange((prev) => updateBlockData(prev, id, data));
    }, [applyTreeChange]);
    const duplicateNode = useCallback((id) => {
        applyTreeChange((prev) => {
            const node = findNode(prev, id);
            if (!node)
                return prev;
            const parent = findParent(prev, id);
            if (!parent)
                return prev;
            const siblings = parent.children;
            const idx = siblings.findIndex((c) => c.id === id);
            const cloned = regenerateIds(node);
            return addNode(prev, parent.id, cloned, idx + 1);
        });
    }, [applyTreeChange]);
    const moveNodeUp = useCallback((id) => {
        applyTreeChange((prev) => {
            const parent = findParent(prev, id);
            if (!parent)
                return prev;
            const siblings = parent.children;
            const idx = siblings.findIndex((c) => c.id === id);
            if (idx <= 0)
                return prev;
            const withoutNode = removeNode(prev, id);
            const node = findNode(prev, id);
            if (!node)
                return prev;
            return addNode(withoutNode, parent.id, deepClone(node), idx - 1);
        });
    }, [applyTreeChange]);
    const moveNodeDown = useCallback((id) => {
        applyTreeChange((prev) => {
            const parent = findParent(prev, id);
            if (!parent)
                return prev;
            const siblings = parent.children;
            const idx = siblings.findIndex((c) => c.id === id);
            if (idx >= siblings.length - 1)
                return prev;
            const withoutNode = removeNode(prev, id);
            const node = findNode(prev, id);
            if (!node)
                return prev;
            return addNode(withoutNode, parent.id, deepClone(node), idx + 1);
        });
    }, [applyTreeChange]);
    const undo = useCallback(() => {
        if (undoStack.current.length === 0)
            return;
        const prev = undoStack.current[undoStack.current.length - 1];
        undoStack.current = undoStack.current.slice(0, -1);
        setTree((current) => {
            redoStack.current = [...redoStack.current, current];
            setCanUndo(undoStack.current.length > 0);
            setCanRedo(true);
            return prev;
        });
    }, []);
    const redo = useCallback(() => {
        if (redoStack.current.length === 0)
            return;
        const next = redoStack.current[redoStack.current.length - 1];
        redoStack.current = redoStack.current.slice(0, -1);
        setTree((current) => {
            undoStack.current = [...undoStack.current, current];
            setCanRedo(redoStack.current.length > 0);
            setCanUndo(true);
            return next;
        });
    }, []);
    const markClean = useCallback(() => {
        setDirty(false);
    }, []);
    const replaceTree = useCallback((newTree) => {
        setTree((prev) => {
            pushHistory(prev);
            setDirty(true);
            setCanUndo(true);
            setCanRedo(false);
            return newTree;
        });
    }, [pushHistory]);
    return {
        tree,
        selectedNodeId,
        selectedNode,
        deviceMode,
        activeTab,
        pageSettings,
        dirty,
        canUndo,
        canRedo,
        showGridOverlay,
        selectNode,
        setDeviceMode,
        setActiveTab,
        setPageSettings,
        setShowGridOverlay,
        addSection,
        addRowToSection,
        addBlockToColumn,
        addNodeAtId,
        removeNodeById,
        moveNodeById,
        updateSettings,
        updateBlock,
        duplicateNode,
        moveNodeUp,
        moveNodeDown,
        undo,
        redo,
        markClean,
        replaceTree,
    };
}
//# sourceMappingURL=useBuilderState.js.map