import { useState, useCallback, useRef } from 'react';
import { Edge } from '@xyflow/react';
import { AppNodeType, ContextMenuState, ContextMenuTarget, NodeType } from '../types/node';

interface UseCanvasContextMenuProps {
    nodes: AppNodeType[];
    edges: Edge[];
    setNodes: (updater: (nodes: AppNodeType[]) => AppNodeType[]) => void;
    setEdges: (updater: (edges: Edge[]) => Edge[]) => void;
    takeSnapshot: () => void;
    setClipboard: (node: AppNodeType) => void;
    handleCreateAndConnectManager: (type: NodeType, nodeId: string | undefined, nodes: AppNodeType[], edges: Edge[], takeSnapshot: () => void) => void;
}

/**
 * Hook to manage Canvas context menu
 * Extracts context menu logic from Canvas component
 */
export const useCanvasContextMenu = ({
    nodes,
    edges,
    setNodes,
    setEdges,
    takeSnapshot,
    setClipboard,
    handleCreateAndConnectManager
}: UseCanvasContextMenuProps) => {
    
    const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
    const [contextMenuTarget, setContextMenuTarget] = useState<ContextMenuTarget | null>(null);
    
    // Replacement input refs
    const replaceVideoInputRef = useRef<HTMLInputElement>(null);
    const replaceImageInputRef = useRef<HTMLInputElement>(null);
    const replacementTargetRef = useRef<string | null>(null);

    const onNodeContextMenu = useCallback(
        (event: React.MouseEvent, node: AppNodeType) => {
            event.preventDefault();
            setContextMenu({
                visible: true,
                x: event.clientX,
                y: event.clientY,
                id: node.id,
            });
            setContextMenuTarget({ type: 'node', id: node.id });
        },
        []
    );

    const onEdgeContextMenu = useCallback(
        (event: React.MouseEvent, edge: Edge) => {
            event.preventDefault();
            setContextMenu({
                visible: true,
                x: event.clientX,
                y: event.clientY,
                id: edge.id,
            });
            setContextMenuTarget({ type: 'connection', id: edge.id });
        },
        []
    );

    const onPaneContextMenu = useCallback(
        (event: React.MouseEvent | MouseEvent) => {
            event.preventDefault();
            setContextMenu({
                visible: true,
                x: event.clientX,
                y: event.clientY,
            });
            setContextMenuTarget({ type: 'pane' });
        },
        []
    );

    const onPaneClick = useCallback(() => setContextMenu(null), []);

    const onPaneDoubleClick = useCallback((event: React.MouseEvent) => {
        event.preventDefault();
        if ((event.target as HTMLElement).classList.contains('react-flow__pane')) {
            setContextMenu({ 
                visible: true, 
                x: event.clientX, 
                y: event.clientY, 
                id: 'create-menu',
            });
            setContextMenuTarget({ type: 'create' });
        }
    }, []);

    const handleCopyNode = useCallback((nodeId: string) => {
        const targetNode = nodes.find(n => n.id === nodeId);
        if (targetNode && targetNode.type === 'appNode') {
            setClipboard(targetNode);
        }
    }, [nodes, setClipboard]);

    const handleReplaceMedia = useCallback((nodeId: string, mediaType: 'image' | 'video') => {
        replacementTargetRef.current = nodeId;
        if (mediaType === 'video') replaceVideoInputRef.current?.click();
        else replaceImageInputRef.current?.click();
    }, []);

    const handleDeleteNode = useCallback((nodeId: string) => {
        takeSnapshot();
        setNodes((nds) => nds.filter(n => n.id !== nodeId));
    }, [setNodes, takeSnapshot]);

    const handleDeleteEdge = useCallback((edgeId: string) => {
        takeSnapshot();
        setEdges((eds) => eds.filter(e => e.id !== edgeId));
    }, [setEdges, takeSnapshot]);

    const handleReplaceFile = useCallback((e: React.ChangeEvent<HTMLInputElement>, type: 'image' | 'video') => {
        takeSnapshot();
        const file = e.target.files?.[0];
        const targetId = replacementTargetRef.current;
        if (file && targetId) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const result = e.target?.result as string;
                if (type === 'image') {
                    setNodes((nds) => nds.map(n => (n.id === targetId && n.type === 'appNode') ? { ...n, data: { ...n.data, image: result } } : n));
                } else {
                    setNodes((nds) => nds.map(n => (n.id === targetId && n.type === 'appNode') ? { ...n, data: { ...n.data, videoUri: result } } : n));
                }
            };
            reader.readAsDataURL(file);
        }
        e.target.value = ''; 
        setContextMenu(null); 
        replacementTargetRef.current = null; 
    }, [setNodes, takeSnapshot]);

    const handleCreateAndConnect = useCallback((type: NodeType) => {
        handleCreateAndConnectManager(type, contextMenuTarget?.nodeId, nodes, edges, takeSnapshot);
        setContextMenu(null);
    }, [handleCreateAndConnectManager, contextMenuTarget, nodes, edges, takeSnapshot]);

    return {
        contextMenu,
        contextMenuTarget,
        setContextMenu,
        setContextMenuTarget,
        replaceVideoInputRef,
        replaceImageInputRef,
        onNodeContextMenu,
        onEdgeContextMenu,
        onPaneContextMenu,
        onPaneClick,
        onPaneDoubleClick,
        handleCopyNode,
        handleReplaceMedia,
        handleDeleteNode,
        handleDeleteEdge,
        handleReplaceFile,
        handleCreateAndConnect
    };
};
