import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { Handle, Position, NodeProps, Node } from '@xyflow/react';
import useGraphStore from '../store';
import { shallow } from 'zustand/shallow';
import { GraphState } from '../types';

export type GraphNode = Node<{
    label: string;
    color?: string;
    level?: number;
}, 'graph-node'>;

const getLevelStyles = (level: number = 0) => {
    const styles = {
        0: {
            container: 'bg-[#2B4B6F] text-white',
            handle: 'bg-[#2B4B6F]',
            fontSize: 'text-lg'
        },
        1: {
            container: 'bg-blue-300 text-white',
            handle: 'bg-[#3A5F84]',
            fontSize: 'text-base'
        },
        2: {
            container: 'bg-gray-100',
            handle: 'bg-[#496F96]',
            fontSize: 'text-base'
        }
    };
    return styles[level as keyof typeof styles]
};


const baseTextStyles = `
text-center
break-words
whitespace-pre-wrap
`;
const handleStyles = `
    w-2.5 h-2.5
    border-2 border-white/80
    rounded-full
    transition-colors
    duration-200
    opacity-80
    hover:opacity-100
`;
const selector = (store: GraphState) => ({
    updateNode: store.updateNode,
});

export const GraphNode = memo(({ id, selected, data, isConnectable }: NodeProps<GraphNode>) => {
    const { updateNode } = useGraphStore(selector, shallow);
    const [isEditing, setIsEditing] = useState(false);
    const levelStyles = getLevelStyles(data.level);
    const [inputValue, setInputValue] = useState(data.label);
    const [isComposing, setIsComposing] = useState(false);
    const updateTextareaHeight = useCallback((element: HTMLTextAreaElement) => {
        element.style.height = 'auto';
        element.style.height = `${element.scrollHeight}px`;
    }, []);
    const handleChange = useCallback((evt: React.ChangeEvent<HTMLTextAreaElement>) => {
        const newValue = evt.target.value;
        setInputValue(newValue);
        updateNode(id, { label: newValue });
        updateTextareaHeight(evt.target);
    }, [updateNode, id, updateTextareaHeight]);
    const handleKeyDown = useCallback((evt: React.KeyboardEvent<HTMLTextAreaElement>) => {
        if (!isEditing) {
            if (/^[a-zA-Z0-9]$/.test(evt.key)) {
                setIsEditing(true);
                setInputValue(evt.key); // 将第一个字符添加到现有内容后
                updateNode(id, { label: evt.key });
            }
            if (evt.key === ' ') {
                setIsEditing(true);
                setInputValue(data.label); // 将第一个字符添加到现有内容后
                updateNode(id, { label: data.label });
            }
            evt.preventDefault(); // 阻止默认行为
            evt.stopPropagation(); // 阻止事件冒泡
        } else if (isEditing && evt.key === 'Enter' && !evt.shiftKey && !isComposing) {
            setIsEditing(false);
            evt.preventDefault();
        }
    }, [isEditing, isComposing, data.label, id, updateNode]);
    const handleDoubleClick = useCallback(() => {
        setIsEditing(true);
    }, []);
    const handleBlur = useCallback(() => setIsEditing(false), []);
    // 添加 ref 来获取父元素
    const containerRef = useRef<HTMLDivElement>(null);
    const textareaRef = useRef<HTMLTextAreaElement | null>(null);

    useEffect(() => {
        if (isEditing && textareaRef.current) {
            updateTextareaHeight(textareaRef.current);
            // 聚焦并将光标移到末尾
            textareaRef.current.focus();
            const length = textareaRef.current.value.length;
            textareaRef.current.setSelectionRange(length, length);
        }
    }, [isEditing, updateTextareaHeight]);

    return (
        <div
            ref={containerRef}
            className={`
                flex items-center  justify-center
                 rounded-md
       
                  max-w-64 
            ${levelStyles.container}
            ${selected ? 'ring-2 ring-[#3688FF]/30 shadow-lg' : ''}
            ${isEditing ? 'ring-2 ring-white/50' : ''}
        `}
        >

            <textarea
                ref={textareaRef}
                defaultValue={data.label}
                onChange={(evt) => handleChange(evt as any)}
                onBlur={handleBlur}
                value={inputValue}
                onKeyDown={handleKeyDown}
                onCompositionStart={() => setIsComposing(true)}
                onCompositionEnd={() => setIsComposing(false)}
                className={`
                    ${isEditing ? 'nodrag' : ''}
                    bg-transparent
                    focus:outline-none
                    ${baseTextStyles}
                    ${levelStyles.fontSize}
                    resize-none
                    overflow-hidden
                    ${!isEditing ? 'cursor-default' : ''}
                `}
                placeholder={isEditing ? "输入节点内容..." : "双击编辑"}
                rows={1}
                readOnly={!isEditing}
                onDoubleClick={handleDoubleClick}
                onInput={(e) => {
                    const target = e.target as HTMLTextAreaElement;
                    target.style.height = 'auto';
                    target.style.height = `${target.scrollHeight}px`;
                }}
            />

            <Handle
                type="target"
                position={Position.Left}
                isConnectable={isConnectable}
                id="target"
                className={`${handleStyles} -ml-[6px] ${levelStyles.handle}`}
            />
            <Handle
                type="source"
                position={Position.Right}
                isConnectable={isConnectable}
                id="source"
                className={`${handleStyles} -mr-[6px] ${levelStyles.handle}`}
            />
        </div>
    );
});

GraphNode.displayName = 'GraphNode';