import React, { useState, useMemo, useCallback } from 'react';
import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react';
import type { FlowNode, ControlPoint } from '../types';
import { convertToDisplayName } from '@/utils/workflow/variableConversion';

/**
 * 自定义边组件
 * 支持hover高亮、样式优化和拖动改变路径
 */
const CustomEdge: React.FC<EdgeProps> = ({
    id,
    sourceX,
    sourceY,
    targetX,
    targetY,
    sourcePosition,
    targetPosition,
    style = {},
    markerEnd,
    label,
    selected,
    data,
}) => {
    const [isHovered, setIsHovered] = useState(false);
    const [isDragging, setIsDragging] = useState(false);
    const { getNodes, setEdges, screenToFlowPosition } = useReactFlow();

    // 从 data 中获取自定义的控制点
    const customControlPoint = data?.controlPoint as ControlPoint | undefined;

    // 将 label 中的 UUID 转换为节点名
    const displayLabel = useMemo(() => {
        if (!label || typeof label !== 'string') {
            return label;
        }

        const allNodes = getNodes() as FlowNode[];
        return convertToDisplayName(label, allNodes);
    }, [label, getNodes]);

    // 计算三个拐点（vertices）：优先用数据中的 vertices；否则从旧的 controlPoint 推导；最后用默认1/4、1/2、3/4
    const vertices: ControlPoint[] = useMemo(() => {
        const dataVertices = (data as any)?.vertices as ControlPoint[] | undefined;
        if (Array.isArray(dataVertices) && dataVertices.length === 3) return dataVertices;
        const cp = customControlPoint;
        if (cp) {
            return [
                { x: (sourceX + cp.x) / 2, y: (sourceY + cp.y) / 2 },
                { x: cp.x, y: cp.y },
                { x: (cp.x + targetX) / 2, y: (cp.y + targetY) / 2 },
            ];
        }
        return [
            { x: sourceX + (targetX - sourceX) * 0.25, y: sourceY + (targetY - sourceY) * 0.25 },
            { x: (sourceX + targetX) / 2, y: (sourceY + targetY) / 2 },
            { x: sourceX + (targetX - sourceX) * 0.75, y: sourceY + (targetY - sourceY) * 0.75 },
        ];
    }, [data, customControlPoint, sourceX, sourceY, targetX, targetY]);

    // 若数据中缺少 vertices，则在首次渲染时写回，确保后续保存能持久化
    React.useEffect(() => {
        const hasDataVertices = Array.isArray((data as any)?.vertices) && (data as any).vertices.length === 3;
        if (!hasDataVertices) {
            setEdges((eds) => eds.map(ed => ed.id === id ? { ...ed, data: { ...ed.data, vertices } } : ed));
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    // 生成路径：使用 Catmull-Rom -> Cubic Bezier 插值，曲线严格经过拐点
    const [edgePath, labelX, labelY] = useMemo(() => {
        // 拼接点序列：起点、3个拐点、终点
        const pts = [
            { x: sourceX, y: sourceY },
            vertices[0],
            vertices[1],
            vertices[2],
            { x: targetX, y: targetY },
        ];
        // Catmull-Rom 转三次贝塞尔：C1 = P0 + (P1 - P_{-1})/6, C2 = P1 - (P2 - P0)/6
        const segs: string[] = [];
        for (let i = 0; i < pts.length - 1; i++) {
            const p_1 = i === 0 ? pts[i] : pts[i - 1];
            const p0 = pts[i];
            const p1 = pts[i + 1];
            const p2 = i + 2 < pts.length ? pts[i + 2] : p1;
            const c1x = p0.x + (p1.x - p_1.x) / 6;
            const c1y = p0.y + (p1.y - p_1.y) / 6;
            const c2x = p1.x - (p2.x - p0.x) / 6;
            const c2y = p1.y - (p2.y - p0.y) / 6;
            segs.push(`C ${c1x},${c1y} ${c2x},${c2y} ${p1.x},${p1.y}`);
        }
        const path = `M ${pts[0].x},${pts[0].y} ${segs.join(' ')}`;
        // 标签显示在第二个拐点
        return [path, vertices[1].x, vertices[1].y] as [string, number, number];
    }, [vertices, sourceX, sourceY, targetX, targetY]);

    // 拖动处理（支持第 idx 个拐点）
    const handleVertexMouseDown = useCallback((idx: number, e: React.MouseEvent) => {
        e.stopPropagation();
        e.preventDefault();
        setIsDragging(true);

        const handleMove = (moveEvent: MouseEvent) => {
            const flowPosition = screenToFlowPosition({ x: moveEvent.clientX, y: moveEvent.clientY });
            setEdges((eds) => eds.map(ed => {
                if (ed.id !== id) return ed;
                const old = (ed as any).data?.vertices as ControlPoint[] | undefined;
                const base = Array.isArray(old) && old.length === 3 ? [...old] : vertices.slice();
                base[idx] = { x: flowPosition.x, y: flowPosition.y };
                return { ...ed, data: { ...ed.data, vertices: base } } as any;
            }));
        };

        const handleUp = () => {
            setIsDragging(false);
            window.removeEventListener('mousemove', handleMove);
            window.removeEventListener('mouseup', handleUp);
        };

        window.addEventListener('mousemove', handleMove);
        window.addEventListener('mouseup', handleUp);
    }, [id, setEdges, screenToFlowPosition, vertices]);

    // 根据状态确定样式
    const edgeStyle = {
        ...style,
        stroke: selected ? '#3b82f6' : isHovered ? '#64748b' : '#94a3b8',
        strokeWidth: selected ? 3 : isHovered ? 2.5 : 2,
        transition: 'all 0.2s ease',
    };

    // ✅ 修复：确保 markerEnd 是对象后再 spread
    const markerEndStyle = (() => {
        if (!markerEnd || typeof markerEnd !== 'object') return markerEnd;
        const markerObj = markerEnd as Record<string, any>;
        if (selected) return { ...markerObj, color: '#3b82f6' };
        if (isHovered) return { ...markerObj, color: '#64748b' };
        return markerEnd;
    })();

    return (
        <>
            <BaseEdge
                id={id}
                path={edgePath}
                style={edgeStyle}
                markerEnd={markerEndStyle as any}
            />
            
            {/* 增加点击区域 */}
            <path
                d={edgePath}
                fill="none"
                stroke="transparent"
                strokeWidth={20}
                style={{ cursor: isDragging ? 'grabbing' : 'grab' }}
                onMouseEnter={() => setIsHovered(true)}
                onMouseLeave={() => setIsHovered(false)}
            />

            {/* 控制点（三个拐点，直接在SVG中渲染，可拖动） */}
            {(selected || isHovered) && (
                <g>
                    {vertices.map((pt, idx) => (
                        <g key={`v-${idx}`}>
                            <circle
                                cx={pt.x}
                                cy={pt.y}
                                r={8}
                                fill={isDragging ? '#2563eb' : '#3b82f6'}
                                stroke="white"
                                strokeWidth={2}
                                style={{ cursor: isDragging ? 'grabbing' : 'grab', filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.3))', pointerEvents: 'all' }}
                                onMouseDown={(e) => handleVertexMouseDown(idx, e)}
                            />
                            <circle
                                cx={pt.x}
                                cy={pt.y}
                                r={15}
                                fill="transparent"
                                style={{ cursor: isDragging ? 'grabbing' : 'grab', pointerEvents: 'all' }}
                                onMouseDown={(e) => handleVertexMouseDown(idx, e)}
                            />
                        </g>
                    ))}
                </g>
            )}

            {/* 边标签 */}
            {displayLabel && (
                <EdgeLabelRenderer>
                    <div
                        style={{
                            position: 'absolute',
                            transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
                            fontSize: '12px',
                            fontWeight: '500',
                            color: selected ? '#3b82f6' : '#64748b',
                            background: 'white',
                            padding: '4px 10px',
                            borderRadius: '6px',
                            border: `1px solid ${selected ? '#3b82f6' : '#e5e7eb'}`,
                            boxShadow: '0 2px 6px rgba(0,0,0,0.1)',
                            pointerEvents: 'all',
                            cursor: 'pointer',
                            transition: 'all 0.2s ease',
                        }}
                        onMouseEnter={() => setIsHovered(true)}
                        onMouseLeave={() => setIsHovered(false)}
                    >
                        {displayLabel}
                    </div>
                </EdgeLabelRenderer>
            )}
        </>
    );
};

export default CustomEdge;

