import { useEffect, useRef, useState } from 'react';
import { useProjectStore } from '@/lib/store/project';
import { saveCanvasStateToStorage } from '../services/storage';
import { AppNodeType } from '../types/node';
import { Edge } from '@xyflow/react';
import { getStorageKey, getHistoryKey } from './persistenceUtils';
import { useCanvasStore } from '@/lib/store/canvasStore';
import { useMutation } from '@tanstack/react-query';
import { CanvasMetadata } from '@/types';
import { logger } from '@/lib/utils/logger';

const log = logger.namespace('CanvasPersistence');

interface UseCanvasPersistenceProps {
    nodes: AppNodeType[];
    edges: Edge[];
    activeCanvasId: string | null;
    activeCanvasType: string;
    isCanvasLoaded: boolean;
    canvasMetadata?: CanvasMetadata | null;
}

// Smart debounce delays based on operation type
const DEBOUNCE_DELAYS = {
    'node-move': 1000,      // Dragging nodes: 1000ms
    'node-resize': 1000,    // Resizing nodes: 1000ms
    'text-edit': 500,       // Modifying text: 500ms
    'node-add': 200,        // Adding nodes: 200ms
    'node-delete': 200,     // Deleting nodes: 200ms
    'other': 500,           // Other operations: 500ms (default)
    'null': 500             // No operation type: 500ms (default)
} as const;

export const useCanvasPersistence = ({
    nodes,
    edges,
    activeCanvasId,
    activeCanvasType,
    isCanvasLoaded,
    canvasMetadata
}: UseCanvasPersistenceProps) => {
    const projectId = useProjectStore((s) => s.id);
    const generationHistory = useCanvasStore(state => state.generationHistory);
    const lastOperationType = useCanvasStore(state => state.lastOperationType);
    const isDirty = useCanvasStore(state => state.isDirty);
    const setSaving = useCanvasStore(state => state.setSaving);
    const setLastSavedAt = useCanvasStore(state => state.setLastSavedAt);
    
    // Track save error state
    const [saveError, setSaveError] = useState<string | null>(null);
    
    // Mutation for saving canvas state
    const { mutate: saveCanvas, isPending: isSavingMutation } = useMutation({
        mutationFn: async (data: { nodes: AppNodeType[], edges: Edge[], history: any[] }) => {
            setSaving(true);
            const key = getStorageKey(activeCanvasId, activeCanvasType, projectId);
            return await saveCanvasStateToStorage(
                key, 
                data, 
                projectId || undefined,
                canvasMetadata || undefined
            );
        },
        onSuccess: () => {
            setSaving(false);
            setLastSavedAt(Date.now());
            setSaveError(null);
        },
        onError: (error) => {
            setSaving(false);
            log.error('Failed to save canvas state:', error);
            const errorMessage = error instanceof Error 
                ? error.message 
                : '保存画布失败，请稍后重试';
            setSaveError(errorMessage);
        }
    });

    // Mutation for saving history
    const { mutate: saveHistory, isPending: isSavingHistory } = useMutation({
        mutationFn: async (historyData: any[]) => {
            const key = getHistoryKey(projectId);
            return await saveCanvasStateToStorage(key, { nodes: [], edges: [], history: historyData }, projectId || undefined);
        },
        onError: (error) => {
             log.error('Failed to save history:', error);
        }
    });

    const canvasSaveTimeoutRef = useRef<NodeJS.Timeout>(null);
    const historySaveTimeoutRef = useRef<NodeJS.Timeout>(null);

    // Manual save function that bypasses debounce
    const saveImmediately = () => {
        if (!isCanvasLoaded) {
            log.warn('Cannot save: canvas not loaded');
            return;
        }

        // Clear any pending debounced saves
        if (canvasSaveTimeoutRef.current) {
            clearTimeout(canvasSaveTimeoutRef.current);
            canvasSaveTimeoutRef.current = null;
        }

        // Save immediately
        saveCanvas({ nodes, edges, history: generationHistory });
        log.log('Manual save triggered');
    };

    // Auto-save Canvas State with smart debounce based on operation type
    useEffect(() => {
        if (!isCanvasLoaded || !isDirty) return;

        if (canvasSaveTimeoutRef.current) {
            clearTimeout(canvasSaveTimeoutRef.current);
        }

        const delay = DEBOUNCE_DELAYS[lastOperationType || 'null'];

        // Use throttle/debounce with maxWait to ensure updates aren't starved indefinitely
        // However, since we're using simple setTimeout, we'll implement a custom maxWait logic
        // If we've been dirty for too long (e.g., 10 seconds), force a save
        const MAX_WAIT = 10000; // 10 seconds max wait time
        
        // Calculate time since last save (or since becoming dirty if no save yet)
        const timeSinceLastSave = Date.now() - (useCanvasStore.getState().lastSavedAt || 0);
        
        // If we've exceeded maxWait, save immediately (on next tick)
        if (timeSinceLastSave > MAX_WAIT) {
             log.log('Max wait exceeded, forcing save');
             saveCanvas({ nodes, edges, history: generationHistory });
             return;
        }

        canvasSaveTimeoutRef.current = setTimeout(() => {
            saveCanvas({ nodes, edges, history: generationHistory });
        }, delay);

        return () => {
            if (canvasSaveTimeoutRef.current) {
                clearTimeout(canvasSaveTimeoutRef.current);
            }
        };
    }, [nodes, edges, generationHistory, isCanvasLoaded, isDirty, activeCanvasId, activeCanvasType, projectId, canvasMetadata, lastOperationType, saveCanvas]);

    // Handle unsaved changes on window close
    useEffect(() => {
        const handleBeforeUnload = (e: BeforeUnloadEvent) => {
            if (isDirty) {
                e.preventDefault();
                e.returnValue = '您有未保存的更改，确定要离开吗？';
                return e.returnValue;
            }
        };

        window.addEventListener('beforeunload', handleBeforeUnload);
        return () => window.removeEventListener('beforeunload', handleBeforeUnload);
    }, [isDirty]);

    // Save Global History (if separate from canvas state)
    useEffect(() => {
        if (historySaveTimeoutRef.current) {
            clearTimeout(historySaveTimeoutRef.current);
        }

        historySaveTimeoutRef.current = setTimeout(() => {
            saveHistory(generationHistory);
        }, 1000);

        return () => {
             if (historySaveTimeoutRef.current) {
                clearTimeout(historySaveTimeoutRef.current);
            }
        };
    }, [generationHistory, projectId, saveHistory]);

    // Return manual save function, saving status, and error state
    return {
        saveImmediately,
        isSaving: isSavingMutation || isSavingHistory,
        saveError,
        isDirty
    };
};
