import React, {useEffect, useRef, useState} from 'react';
import {useNavigate, useParams} from 'react-router-dom';
import {Button, Card, Layout, message, Space, Spin, Drawer, Form, Dropdown} from 'antd';
import {ArrowLeftOutlined, SaveOutlined} from '@ant-design/icons';
import {getDefinition, updateDefinition} from '../../service';
import {WorkflowDefinition, WorkflowStatus} from '../../../Workflow/types';
import {Graph, Node, Cell, Edge, Shape} from '@antv/x6';
import '@antv/x6-react-shape';
import {Selection} from '@antv/x6-plugin-selection';
import {History} from '@antv/x6-plugin-history';
import {Clipboard} from '@antv/x6-plugin-clipboard';
import {Transform} from '@antv/x6-plugin-transform';
import {Keyboard} from '@antv/x6-plugin-keyboard';
import {Snapline} from '@antv/x6-plugin-snapline';
import {MiniMap} from '@antv/x6-plugin-minimap';
import './index.module.less';
import NodePanel from './components/NodePanel';
import NodeConfig from './components/NodeConfig';
import Toolbar from './components/Toolbar';
import {NodeType, getNodeTypes} from './service';
import {DeleteOutlined, CopyOutlined, SettingOutlined, ClearOutlined, FullscreenOutlined} from '@ant-design/icons';
import EdgeConfig from './components/EdgeConfig';
import { validateFlow, hasCycle } from './validate';
import { generateNodeStyle, generatePorts, calculateNodePosition, calculateCanvasPosition } from './utils/nodeUtils';
import { Position } from './types';
import { NODE_CONFIG } from './configs/nodeConfig';
import { isWorkflowError } from './utils/errors';

const {Sider, Content} = Layout;

interface NodeData {
    type: string;
    name?: string;
    description?: string;
    config: {
        executor?: string;
        retryTimes?: number;
        retryInterval?: number;
        script?: string;
        timeout?: number;
        workingDirectory?: string;
        environment?: string;
        successExitCode?: string;
        [key: string]: any;
    };
}

const FlowDesigner: React.FC = () => {
    const navigate = useNavigate();
    const {id} = useParams<{ id: string }>();
    const [loading, setLoading] = useState(false);
    const [detail, setDetail] = useState<WorkflowDefinition>();
    const containerRef = useRef<HTMLDivElement>(null);
    const graphRef = useRef<Graph>();
    const [graph, setGraph] = useState<Graph>();
    const draggedNodeRef = useRef<NodeType>();
    const [configVisible, setConfigVisible] = useState(false);
    const [currentNode, setCurrentNode] = useState<Node>();
    const [currentNodeType, setCurrentNodeType] = useState<NodeType>();
    const [nodeTypes, setNodeTypes] = useState<NodeType[]>([]);
    const [form] = Form.useForm();
    const [currentEdge, setCurrentEdge] = useState<Edge>();
    const [edgeConfigVisible, setEdgeConfigVisible] = useState(false);
    const [edgeForm] = Form.useForm();

    // 右键菜单状态
    const [contextMenu, setContextMenu] = useState<{
        x: number;
        y: number;
        visible: boolean;
        type: 'node' | 'edge' | 'canvas';
        cell?: Cell;
    }>({
        x: 0,
        y: 0,
        visible: false,
        type: 'canvas',
    });

    // 右键菜单项
    const menuItems = {
        node: [
            {
                key: 'delete',
                label: '删除节点',
                icon: <DeleteOutlined />,
                onClick: () => {
                    if (contextMenu.cell) {
                        contextMenu.cell.remove();
                    }
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
            {
                key: 'copy',
                label: '复制节点',
                icon: <CopyOutlined />,
                onClick: () => {
                    if (contextMenu.cell && contextMenu.cell.isNode()) {
                        const pos = contextMenu.cell.position();
                        const newCell = contextMenu.cell.clone();
                        newCell.position(pos.x + 20, pos.y + 20);
                        graph?.addCell(newCell);
                    }
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
            {
                key: 'config',
                label: '配置节点',
                icon: <SettingOutlined />,
                onClick: () => {
                    if (contextMenu.cell && contextMenu.cell.isNode()) {
                        setCurrentNode(contextMenu.cell);
                        const data = contextMenu.cell.getData() as NodeData;
                        const nodeType = nodeTypes.find(type => type.code === data.type);
                        if (nodeType) {
                            setCurrentNodeType(nodeType);
                            const formValues = {
                                name: data.name || nodeType.name,
                                description: data.description,
                                ...data.config
                            };
                            form.setFieldsValue(formValues);
                        }
                        setConfigVisible(true);
                    }
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
        ],
        edge: [
            {
                key: 'config',
                label: '配置连线',
                icon: <SettingOutlined />,
                onClick: () => {
                    if (contextMenu.cell && contextMenu.cell.isEdge()) {
                        handleEdgeConfig(contextMenu.cell);
                    }
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
            {
                key: 'delete',
                label: '删除连线',
                icon: <DeleteOutlined />,
                onClick: () => {
                    if (contextMenu.cell) {
                        contextMenu.cell.remove();
                    }
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
        ],
        canvas: [
            {
                key: 'clear',
                label: '清空画布',
                icon: <ClearOutlined />,
                onClick: () => {
                    graph?.clearCells();
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
            {
                key: 'fit',
                label: '适应画布',
                icon: <FullscreenOutlined />,
                onClick: () => {
                    graph?.zoomToFit({ padding: 20 });
                    setContextMenu(prev => ({ ...prev, visible: false }));
                },
            },
        ],
    };

    // 获取所有节点类型
    const fetchNodeTypes = async () => {
        try {
            const types = await getNodeTypes({enabled: true});
            setNodeTypes(types);
            return types;
        } catch (error) {
            console.error('获取节点类型失败:', error);
            message.error('获取节点类型失败');
            return [];
        }
    };

    // 首次加载获取节点类型
    useEffect(() => {
        fetchNodeTypes();
    }, []);

    // 初始化图形
    const initGraph = () => {
        if (!containerRef.current) return;

        const graph = new Graph({
            container: containerRef.current,
            grid: {
                visible: true,
                type: 'mesh',
                size: 10,
                args: {
                    color: '#e5e5e5',
                    thickness: 1,
                },
            },
            mousewheel: {
                enabled: true,
                modifiers: ['ctrl', 'meta'],
                minScale: 0.5,
                maxScale: 2,
            },
            connecting: {
                snap: true,
                allowBlank: false,
                allowLoop: false,
                allowNode: false,
                allowEdge: false,
                connector: {
                    name: 'rounded',
                    args: {
                        radius: 8,
                    },
                },
                router: {
                    name: 'manhattan',
                    args: {
                        padding: 1,
                    },
                },
                validateConnection({sourceCell, targetCell, sourceMagnet, targetMagnet}) {
                    if (sourceCell === targetCell) {
                        return false;
                    }
                    if (!sourceMagnet || !targetMagnet) {
                        return false;
                    }
                    return true;
                },
            },
            defaultEdge: {
                attrs: {
                    line: {
                        stroke: '#5F95FF',
                        strokeWidth: 1,
                        targetMarker: {
                            name: 'classic',
                            size: 8,
                        },
                    },
                },
                router: {
                    name: 'manhattan',
                    args: {
                        padding: 1,
                    },
                },
                connector: {
                    name: 'rounded',
                    args: {
                        radius: 8,
                    },
                },
                labels: [
                    {
                        attrs: {
                            label: {
                                text: '',
                                fill: '#333',
                                fontSize: 12,
                            },
                            rect: {
                                fill: '#fff',
                                stroke: '#5F95FF',
                                strokeWidth: 1,
                                rx: 3,
                                ry: 3,
                                refWidth: 1,
                                refHeight: 1,
                                refX: 0,
                                refY: 0,
                            },
                        },
                        position: {
                            distance: 0.5,
                            offset: {
                                x: 0,
                                y: -10,
                            },
                        },
                    },
                ],
            },
            highlighting: {
                magnetAvailable: {
                    name: 'stroke',
                    args: {
                        padding: 4,
                        attrs: {
                            strokeWidth: 4,
                            stroke: '#52c41a',
                        },
                    },
                },
                magnetAdsorbed: {
                    name: 'stroke',
                    args: {
                        padding: 4,
                        attrs: {
                            strokeWidth: 4,
                            stroke: '#1890ff',
                        },
                    },
                },
            },
            keyboard: {
                enabled: true,
            },
            clipboard: {
                enabled: true,
            },
            history: {
                enabled: true,
            },
            snapline: {
                enabled: true,
            },
            translating: {
                restrict: true,
            },
            background: {
                color: '#ffffff',  // 画布背景色
            },
        });

        // 启用必要的功能
        graph.use(
            new Selection({
                enabled: true,
                multiple: true,
                rubberband: true,
                rubberEdge: true,
                movable: true,
                showNodeSelectionBox: true,
                showEdgeSelectionBox: true,
                selectCellOnMoved: false,
                selectEdgeOnMoved: false,
                selectNodeOnMoved: false,
                className: 'node-selected',
                strict: true,
            })
        );

        graph.use(
            new History({
                enabled: true,
                beforeAddCommand: (event: string, args: any) => {
                    if (event === 'cell:change:*') {
                        return true;
                    }
                    return true;
                },
            })
        );

        graph.use(
            new Clipboard({
                enabled: true,
            })
        );

        graph.use(
            new Transform({
                resizing: {
                    enabled: true,
                    minWidth: 1,
                    minHeight: 1,
                    orthogonal: true,
                    restricted: true,
                },
                rotating: {
                    enabled: true,
                    grid: 15,
                },
            })
        );

        graph.use(
            new Keyboard({
                enabled: true,
            })
        );

        graph.use(
            new Snapline({
                enabled: true,
            })
        );

        // 启用小地图
        graph.use(
            new MiniMap({
                container: document.getElementById('workflow-minimap'),
                width: 200,
                height: 150,
                padding: 10,
                scalable: false,
                minScale: 0.5,
                maxScale: 2,
                graphOptions: {
                    async: true,
                    // 简化节点渲染
                    grid: false,
                    background: {
                        color: '#f5f5f5',
                    },
                },
            })
        );

        // 绑定右键菜单事件
        graph.on('cell:contextmenu', ({ cell, e }) => {
            e.preventDefault();
            setContextMenu({
                x: e.clientX,
                y: e.clientY,
                visible: true,
                type: cell.isNode() ? 'node' : 'edge',
                cell,
            });
        });

        graph.on('blank:contextmenu', ({ e }) => {
            e.preventDefault();
            setContextMenu({
                x: e.clientX,
                y: e.clientY,
                visible: true,
                type: 'canvas',
            });
        });

        // 点击画布时隐藏右键菜单
        graph.on('blank:click', () => {
            setContextMenu(prev => ({ ...prev, visible: false }));
        });

        // 点击节点时隐藏右键菜单
        graph.on('cell:click', () => {
            setContextMenu(prev => ({ ...prev, visible: false }));
        });

        graphRef.current = graph;
        setGraph(graph);

        // 加载流程图数据
        if (detail) {
            loadGraphData(graph, detail);
        }

        // 监听画布拖拽事件
        containerRef.current.addEventListener('dragover', handleDragOver);
        containerRef.current.addEventListener('drop', handleDrop);

        // 监听节点点击事件
        graph.on('node:click', ({node}: { node: Node }) => {
            setCurrentNode(node);
            const data = node.getData() as NodeData;
            console.log('Node clicked, data:', data);

            if (data) {
                // 获取节点类型
                const nodeType = nodeTypes.find(type => type.code === data.type);
                if (nodeType) {
                    setCurrentNodeType(nodeType);

                    // 合并节点基本配置和执器配置
                    const formValues = {
                        name: data.name || nodeType.name,
                        description: data.description,
                        ...data.config  // 直接展开所有配置
                    };

                    console.log('Setting form values:', formValues);
                    form.setFieldsValue(formValues);
                    setConfigVisible(true);
                } else {
                    message.error('未找到对应的节点类型');
                }
            }
        });

        // 监听选择状态变化
        graph.on('selection:changed', () => {
            // 强制更新工具栏状态
            setGraph(graph);
        });
    };

    // 处理拖拽移动
    const handleDragOver = (e: DragEvent) => {
        e.preventDefault();
        e.dataTransfer!.dropEffect = 'copy';
    };

    // 处理拖拽放置
    const handleDrop = (e: DragEvent) => {
        e.preventDefault();
        const nodeType = draggedNodeRef.current;
        if (!nodeType || !graphRef.current || !containerRef.current) {
            message.error('无效的节点类型或画布未初始化');
            return;
        }

        try {
            const rect = containerRef.current.getBoundingClientRect();
            const matrix = graphRef.current.matrix();
            
            // 使用新的工具函数计算画布位置
            const dropPosition = calculateCanvasPosition(
                e.clientX,
                e.clientY,
                rect,
                {
                    scale: matrix.a,
                    offsetX: matrix.e,
                    offsetY: matrix.f,
                }
            );

            // 获取节点配置
            const position = calculateNodePosition(nodeType.code, dropPosition);
            const nodeStyle = generateNodeStyle(nodeType.code);
            const ports = generatePorts(nodeType.code);
            const config = NODE_CONFIG[nodeType.code];

            if (!config) {
                throw new Error(`未找到节点类型 ${nodeType.code} 的配置`);
            }

            // 创建节点
            const node = graphRef.current.addNode({
                ...position,
                ...nodeStyle,
                ports,
                data: {
                    type: nodeType.code,
                    name: config.label, // 使用配置中的中文名称
                    config: {} as any,
                },
            });

            // 选中新创建的节点并打开配置
            graphRef.current.cleanSelection();
            graphRef.current.select(node);
            setCurrentNode(node);
            setCurrentNodeType(nodeType);
            form.setFieldsValue({ name: config.label }); // 使用配置中的中文名称
            setConfigVisible(true);

            message.success('节点创建成功');
        } catch (error) {
            console.error('Error creating node:', error);
            
            if (isWorkflowError(error)) {
                message.error(`创建节点失败：${error.message}`);
            } else {
                message.error('创建节点失败：未知错误');
            }

            // 清理状态
            setCurrentNode(undefined);
            setCurrentNodeType(undefined);
            setConfigVisible(false);
        }
    };

    // 验证Shell节点配置
    function validateShellConfig(config: any): boolean {
        if (!config.script?.trim()) {
            throw new Error('脚本内容不能为空');
        }
        if (config.timeout !== undefined && config.timeout <= 0) {
            throw new Error('超时时间必须大于0');
        }
        if (config.retryTimes !== undefined && config.retryTimes < 0) {
            throw new Error('重试次数不能为负数');
        }
        if (config.retryInterval !== undefined && config.retryInterval < 0) {
            throw new Error('重试间不能为负数');
        }
        return true;
    }

    // 处理配置保存
    const handleConfigSave = async () => {
        try {
            const values = await form.validateFields();
            if (currentNode) {
                const data = currentNode.getData() as NodeData;
                const {name, description, ...config} = values;

                // 如果是Shell节点，验证配置
                if (data.type === 'SHELL' && config.executor === 'SHELL') {
                    validateShellConfig(config);
                }

                // 更新节点数据
                currentNode.setData({
                    ...data,
                    name,
                    description,
                    config,
                });

                // 更新节点标签
                currentNode.setAttrByPath('label/text', name);

                message.success('配置保存成功');
                setConfigVisible(false);
            }
        } catch (error) {
            // 表单验证失败或Shell配置验证失败
            message.error((error as Error).message);
        }
    };

    // 获取详情
    const fetchDetail = async () => {
        if (!id) return;
        setLoading(true);
        try {
            const response = await getDefinition(parseInt(id));
            if (response) {
                setDetail(response);
            }
        } finally {
            setLoading(false);
        }
    };

    // 处理保存
    const handleSave = async () => {
        if (!id || !detail || !graphRef.current || detail.status !== WorkflowStatus.DRAFT) return;

        try {
            // 验证流程
            const result = validateFlow(graphRef.current);
            const hasCycleResult = hasCycle(graphRef.current);
            
            if (hasCycleResult) {
                message.error('流程图中存在循环，请检查');
                return;
            }
            
            if (!result.valid) {
                message.error(result.errors.join('\n'));
                return;
            }

            const graphData = graphRef.current.toJSON();

            // 收集节点配置数据
            const nodes = graphRef.current.getNodes().map(node => {
                const data = node.getData() as NodeData;
                return {
                    id: node.id,
                    type: data.type,
                    name: data.name || '',
                    description: data.description,
                    config: data.config || {}
                };
            });

            // 收集连线配置数据
            const transitions = graphRef.current.getEdges().map(edge => {
                const data = edge.getData() || {};
                return {
                    from: edge.getSourceCellId(),
                    to: edge.getTargetCellId(),
                    condition: data.condition || '',
                    description: data.description || '',
                    priority: data.priority || 0
                };
            });

            // 构建更新数据
            const data = {
                ...detail,
                graphDefinition: JSON.stringify(graphData),
                nodeConfig: JSON.stringify({nodes}),
                transitionConfig: JSON.stringify({transitions})
            };

            await updateDefinition(parseInt(id), data);
            message.success('保存成功');
        } catch (error) {
            message.error('保存失败');
            console.error('保存失败:', error);
        }
    };

    // 处理返回
    const handleBack = () => {
        navigate('/workflow/definition');
    };

    // 首次加载
    useEffect(() => {
        fetchDetail();
    }, [id]);

    // 初始化图形
    useEffect(() => {
        if (detail && containerRef.current) {
            initGraph();
        }
        // 清理事件监听
        return () => {
            if (containerRef.current) {
                containerRef.current.removeEventListener('dragover', handleDragOver);
                containerRef.current.removeEventListener('drop', handleDrop);
            }
            if (graphRef.current) {
                graphRef.current.dispose();
            }
        };
    }, [detail, containerRef.current]);

    useEffect(() => {
        if (!containerRef.current) return;

        const resizeObserver = new ResizeObserver(() => {
            if (graphRef.current) {
                const container = containerRef.current;
                if (container) {
                    const { width, height } = container.getBoundingClientRect();
                    graphRef.current.resize(width, height);
                }
            }
        });

        resizeObserver.observe(containerRef.current);

        return () => {
            resizeObserver.disconnect();
        };
    }, []);

    // 处理节点拖拽开始
    const handleNodeDragStart = (nodeType: NodeType) => {
        draggedNodeRef.current = nodeType;
    };

    // 加载流程图数据
    const loadGraphData = (graph: Graph, detail: WorkflowDefinition) => {
        try {
            // 加载图数据
            const graphData = JSON.parse(detail.graphDefinition);
            graph.fromJSON(graphData);

            // 加载节点配置数据
            if (detail.nodeConfig) {
                const nodeConfigData = JSON.parse(detail.nodeConfig);
                // 更新节点数据和显示
                graph.getNodes().forEach(node => {
                    const nodeConfig = nodeConfigData.nodes.find((n: any) => n.id === node.id);
                    if (nodeConfig) {
                        console.log('Node config found:', nodeConfig.config);
                        const nodeData = {
                            type: nodeConfig.type,
                            name: nodeConfig.name,
                            description: nodeConfig.description,
                            config: nodeConfig.config
                        };
                        console.log('Setting node data:', nodeData);
                        node.setData(nodeData);
                        node.setAttrByPath('label/text', nodeConfig.name);
                    }
                });
            }
        } catch (error) {
            message.error('加载流程图数据失败');
            console.error('加载流程图数据失败:', error);
        }
    };

    // 添加连线配置处理函数
    const handleEdgeConfig = (edge: Edge) => {
        setCurrentEdge(edge);
        const data = edge.getData() || {};
        edgeForm.setFieldsValue(data);
        setEdgeConfigVisible(true);
    };

    // 添加连线配置保存函数
    const handleEdgeConfigSubmit = async () => {
        if (!currentEdge) return;
        
        try {
            const values = await edgeForm.validateFields();
            currentEdge.setData(values);
            
            // 更新连线标签
            if (values.description) {
                currentEdge.setLabelAt(0, values.description);
            }
            
            setEdgeConfigVisible(false);
        } catch (error) {
            // 表单验证失败
        }
    };

    if (loading) {
        return (
            <div style={{textAlign: 'center', padding: 100}}>
                <Spin size="large"/>
            </div>
        );
    }

    return (
        <Card
            title={
                <div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}>
                    <Space>
                        <Button type="primary" icon={<SaveOutlined/>} onClick={handleSave}>保存</Button>
                        <Button icon={<ArrowLeftOutlined/>} onClick={() => navigate(-1)}>返回</Button>
                    </Space>
                </div>
            }
            className="workflow-designer"
        >
            <Layout>
                <Sider width={250} className="workflow-designer-sider">
                    <NodePanel onNodeDragStart={handleNodeDragStart}/>
                </Sider>
                <Layout>
                    <Toolbar graph={graph}/>
                    <Content className="workflow-designer-content">
                        <div ref={containerRef} className="workflow-designer-graph"/>
                        <div id="workflow-minimap" className="workflow-designer-minimap"/>
                        <Dropdown
                            menu={{
                                items: menuItems[contextMenu.type],
                                onClick: ({ key, domEvent }) => {
                                    domEvent.stopPropagation();
                                },
                            }}
                            open={contextMenu.visible}
                            trigger={['contextMenu']}
                        >
                            <div
                                style={{
                                    position: 'fixed',
                                    left: contextMenu.x,
                                    top: contextMenu.y,
                                    width: 1,
                                    height: 1,
                                }}
                            />
                        </Dropdown>
                    </Content>
                </Layout>
            </Layout>

            <Drawer
                title="节点配置"
                width={400}
                open={configVisible}
                onClose={() => setConfigVisible(false)}
                extra={
                    <Space>
                        <Button onClick={() => setConfigVisible(false)}>取消</Button>
                        <Button type="primary" onClick={handleConfigSave}>
                            确定
                        </Button>
                    </Space>
                }
            >
                {currentNodeType && (
                    <NodeConfig nodeType={currentNodeType} form={form}/>
                )}
            </Drawer>

            <Drawer
                title="连线配置"
                placement="right"
                width={400}
                onClose={() => setEdgeConfigVisible(false)}
                open={edgeConfigVisible}
                extra={
                    <Space>
                        <Button onClick={() => setEdgeConfigVisible(false)}>取消</Button>
                        <Button type="primary" onClick={handleEdgeConfigSubmit}>
                            确定
                        </Button>
                    </Space>
                }
            >
                {currentEdge && (
                    <EdgeConfig
                        edge={currentEdge}
                        form={edgeForm}
                        onValuesChange={(changedValues, allValues) => {
                            if (changedValues.description) {
                                currentEdge.setLabelAt(0, changedValues.description);
                            }
                        }}
                    />
                )}
            </Drawer>
        </Card>
    );
};

export default FlowDesigner; 