/**
 * Nodes Slice - 节点状态管理
 */
import { AppNodeType } from '@/components/canvas/types';
import { AppNodeDataSchema } from '@/components/canvas/types/schemas';
import { applyNodeChanges, NodeChange } from '@xyflow/react';
import { CanvasState } from './types';
import { MAX_HISTORY_SIZE } from './types';
import { IncrementalHistory } from '@/lib/utils/historyDiff';

export const createNodesActions = (set: any, get: any) => ({
    setNodes: (updater: AppNodeType[] | ((prev: AppNodeType[]) => AppNodeType[])) => set((state: CanvasState) => {
        const nextNodes = typeof updater === 'function' ? updater(state.nodes) : updater;

        // Optional: Validate all appNodes in development
        if (process.env.NODE_ENV === 'development' && Array.isArray(nextNodes)) {
            nextNodes.forEach(node => {
                if (node.type === 'appNode') {
                    const result = AppNodeDataSchema.safeParse(node.data);
                    if (!result.success) {
                        console.warn(`[CanvasStore] Node ${node.id} has invalid data:`, result.error.format());
                    }
                }
            });
        }

        state.nodes = nextNodes;
        state.isDirty = true;
    }),

    onNodesChange: (changes: NodeChange<AppNodeType>[]) => set((state: CanvasState) => {
        const nodes = applyNodeChanges(changes, state.nodes) as AppNodeType[];
        state.nodes = nodes;
        state.isDirty = true;

        // Check for meaningful changes
        const hasMeaningfulChange = changes.some(c =>
            c.type === 'position' ||
            c.type === 'dimensions' ||
            c.type === 'remove' ||
            c.type === 'add'
        );

        if (hasMeaningfulChange) {
            const posChange = changes.find(c => c.type === 'position');
            const dimChange = changes.find(c => c.type === 'dimensions');

            if (posChange && 'id' in posChange) {
                get().saveHistoryWithMerge({
                    type: 'node-move',
                    nodeId: (posChange as any).id,
                    data: (posChange as any).position
                });
            } else if (dimChange && 'id' in dimChange) {
                get().saveHistoryWithMerge({
                    type: 'node-resize',
                    nodeId: (dimChange as any).id,
                    data: (dimChange as any).dimensions
                });
            } else {
                get().saveHistoryThrottled();
            }
        }
    }),

    addNode: (node: AppNodeType) => {
        // Validate node data
        if (node.type === 'appNode') {
            const result = AppNodeDataSchema.safeParse(node.data);
            if (!result.success) {
                console.error('[CanvasStore] Invalid node data on addNode:', result.error.format());
            }
        }

        set((state: CanvasState) => {
            state.lastOperationType = 'node-add';
        });

        // Ensure history is initialized
        const { incrementalHistory } = get();
        if (!incrementalHistory) {
            const { nodes, edges, groups } = get();
            set((state: CanvasState) => {
                state.incrementalHistory = new IncrementalHistory<{
                    nodes: AppNodeType[];
                    edges: any[];
                    groups: any[];
                }>(
                    { nodes, edges, groups },
                    { maxHistory: MAX_HISTORY_SIZE, snapshotInterval: 10 }
                );
            });
        }

        set((state: CanvasState) => {
            state.nodes.push(node);
            state.isDirty = true;
        });

        get().saveHistory();
    },

    deleteNodes: (ids: string[]) => {
        if (ids.length === 0) return;

        set((state: CanvasState) => {
            state.lastOperationType = 'node-delete';
        });

        const { incrementalHistory } = get();
        if (!incrementalHistory) {
            const { nodes, edges, groups } = get();
            set((state: CanvasState) => {
                state.incrementalHistory = new IncrementalHistory<{
                    nodes: AppNodeType[];
                    edges: any[];
                    groups: any[];
                }>(
                    { nodes, edges, groups },
                    { maxHistory: MAX_HISTORY_SIZE, snapshotInterval: 10 }
                );
            });
        }

        set((state: CanvasState) => {
            state.nodes = state.nodes.filter(n => !ids.includes(n.id));
            state.nodes.forEach(n => {
                if ((n.data as any).inputs) {
                    (n.data as any).inputs = (n.data as any).inputs.filter((i: string) => !ids.includes(i));
                }
            });
            state.edges = state.edges.filter(e => e.source !== ids[0] && e.target !== ids[0]);
            state.selectedNodeIds = [];
            state.isDirty = true;
        });

        get().saveHistory();
    },

    updateNode: (id: string, data: any, size?: any, title?: string) => {
        if (data) {
            const result = AppNodeDataSchema.partial().safeParse(data);
            if (!result.success) {
                console.warn('[CanvasStore] Partial validation warning for updateNode:', result.error.format());
            }
        }

        const isTextEdit = title !== undefined || (data && typeof data === 'object' && 'text' in data);

        set((state: CanvasState) => {
            state.lastOperationType = isTextEdit ? 'text-edit' : 'other';
        });

        if (isTextEdit) {
            get().saveHistoryWithMerge({
                type: 'text-edit',
                nodeId: id,
                data: { data, size, title }
            });
        } else {
            get().saveHistoryThrottled();
        }

        set((state: CanvasState) => {
            const node = state.nodes.find(n => n.id === id);
            if (node) {
                if (data) node.data = { ...node.data, ...data };
                if (title && 'title' in node.data) (node.data as any).title = title;
                if (size) {
                    if (size.width) node.width = size.width;
                    if (size.height) node.height = size.height;
                }
                state.isDirty = true;
            }
        });
    },

    updateNodePosition: (id: string, position: { x: number; y: number }) => {
        set((state: CanvasState) => {
            state.lastOperationType = 'node-move';
        });

        get().saveHistoryWithMerge({
            type: 'node-move',
            nodeId: id,
            data: position
        });

        set((state: CanvasState) => {
            const node = state.nodes.find(n => n.id === id);
            if (node) {
                node.position = position;
                state.isDirty = true;
            }
        });
    },

    updateNodeSize: (id: string, size: { width: number; height: number }) => {
        set((state: CanvasState) => {
            state.lastOperationType = 'node-resize';
        });

        get().saveHistoryWithMerge({
            type: 'node-resize',
            nodeId: id,
            data: size
        });

        set((state: CanvasState) => {
            const node = state.nodes.find(n => n.id === id);
            if (node) {
                if (size.width) node.width = size.width;
                if (size.height) node.height = size.height;
                state.isDirty = true;
            }
        });
    },

    batchUpdate: (updates: () => void) => {
        set(() => {
            updates();
        });
    },
});
