import { useEffect, useRef, useCallback } from 'react';

interface UseAutoSaveOptions {
    /**
     * Debounce delay in milliseconds
     * @default 2000
     */
    delay?: number;
    
    /**
     * Whether auto-save is enabled
     * @default true
     */
    enabled?: boolean;
    
    /**
     * Callback when save starts
     */
    onSaveStart?: () => void;
    
    /**
     * Callback when save completes
     */
    onSaveComplete?: () => void;
    
    /**
     * Callback when save fails
     */
    onSaveError?: (error: Error) => void;
}

/**
 * Hook to implement debounced auto-save functionality
 * Automatically saves canvas state after a period of inactivity
 * 
 * @param data - The data to save (nodes, edges, etc.)
 * @param saveFunction - The function to call to save the data
 * @param options - Configuration options
 * 
 * @example
 * ```tsx
 * const { triggerSave, cancelSave } = useAutoSave(
 *   { nodes, edges },
 *   async (data) => {
 *     await apiClient.put(`/canvas/${canvasId}`, data);
 *   },
 *   { delay: 2000 }
 * );
 * ```
 */
export const useAutoSave = <T>(
    data: T,
    saveFunction: (data: T) => Promise<void>,
    options: UseAutoSaveOptions = {}
) => {
    const {
        delay = 2000,
        enabled = true,
        onSaveStart,
        onSaveComplete,
        onSaveError
    } = options;

    const timeoutRef = useRef<NodeJS.Timeout | null>(null);
    const isSavingRef = useRef(false);
    const lastSavedDataRef = useRef<string>('');

    /**
     * Cancel any pending save
     */
    const cancelSave = useCallback(() => {
        if (timeoutRef.current) {
            clearTimeout(timeoutRef.current);
            timeoutRef.current = null;
        }
    }, []);

    /**
     * Trigger a save immediately
     */
    const triggerSave = useCallback(async () => {
        if (isSavingRef.current) {
            return;
        }

        try {
            isSavingRef.current = true;
            onSaveStart?.();
            
            await saveFunction(data);
            lastSavedDataRef.current = JSON.stringify(data);
            
            onSaveComplete?.();
        } catch (error) {
            onSaveError?.(error as Error);
        } finally {
            isSavingRef.current = false;
        }
    }, [data, saveFunction, onSaveStart, onSaveComplete, onSaveError]);

    /**
     * Schedule a debounced save
     */
    const scheduleSave = useCallback(() => {
        if (!enabled) {
            return;
        }

        // Cancel any existing timeout
        cancelSave();

        // Check if data has changed
        const currentData = JSON.stringify(data);
        if (currentData === lastSavedDataRef.current) {
            return;
        }

        // Schedule new save
        timeoutRef.current = setTimeout(() => {
            triggerSave();
        }, delay);
    }, [enabled, data, delay, cancelSave, triggerSave]);

    /**
     * Auto-save when data changes
     */
    useEffect(() => {
        scheduleSave();

        // 清理up on unmount
        return () => {
            cancelSave();
        };
    }, [data, scheduleSave, cancelSave]);

    return {
        /**
         * Trigger a save immediately, bypassing the debounce
         */
        triggerSave,
        
        /**
         * Cancel any pending save
         */
        cancelSave,
        
        /**
         * Schedule a debounced save
         */
        scheduleSave
    };
};
