import { useCallback, useEffect, useState } from 'react';
import {
  ReactFlow,
  MiniMap,
  Controls,
  Background,
  useNodesState,
  useEdgesState,
  addEdge,
  ReactFlowProvider,
  useStore,
  NodeTypes,
  useReactFlow,
  useStoreApi,
  Panel,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useShallow } from 'zustand/react/shallow';
import { Container, useAddNode, ContainerMenusList, useMenuFlow } from '@abearxiong/flows';
import { useMenuEmitter, ContainerMenusKeys } from '@abearxiong/flows';
import { nanoid } from 'nanoid';
import { Button, message, Tooltip } from 'antd';
import { usePanelStore } from '../store';
import { CompassOutlined, PlusOutlined, SaveOutlined } from '@ant-design/icons';
import { generateId } from '@/utils/nanoid';
import { useMessage } from '@/hooks';
import { NodeProperties } from './properties/NodeProperties';
import { emitter } from '@kevisual/container';
// router: Router
const nodeTypes = {
  container: Container,
};

export const Flow = () => {
  return (
    <ReactFlowProvider>
      <ReactFlowApp />
    </ReactFlowProvider>
  );
};
const ReactFlowApp = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState<any>([]);
  const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
  const panelStore = usePanelStore(
    useShallow((state) => {
      return {
        data: state.data,
        saveNodesEdges: state.saveNodesEdges,
      };
    }),
  );
  useEffect(() => {
    if (panelStore.data?.id) {
      const { data } = panelStore.data || {};
      console.log('data', panelStore.data);
      const nodes = [...data.nodes];
      const edges = [...data.edges];
      console.log('nodes', nodes);
      if (nodes.length === 0) {
        nodes.push({
          id: panelStore.data.id,
          data: {
            label: '容器',
            root: true,
          },
          position: {
            x: 100,
            y: 100,
          },
          type: 'container',
        });
      }
      console.log('nodes', nodes);
      setNodes(nodes as any);
      setEdges(edges);
    } else {
      setNodes([]);
      setEdges([]);
    }
  }, [panelStore.data]);
  useEffect(() => {
    emitter.on('setNodes', _setNodes);
    emitter.on('setEdges', _setEdges);
    return () => {
      emitter.off('setNodes', _setNodes);
      emitter.off('setEdges', _setEdges);
    };
  }, []);
  const _setNodes = (data: any) => {
    setNodes(data);
  };
  const _setEdges = (data: any) => {
    setEdges(data);
  };

  const { menuCom, onContextMenu, onClose } = useMenuFlow(
    (item, cacheData) => {
      emit({
        menu: item,
        data: cacheData,
      });
    },
    {
      menusList: ContainerMenusList,
    },
  );

  const { emit } = useMenuEmitter<ContainerMenusKeys>({
    preview: ({ menu, data }) => {
      console.log('preview', data, message);
      if (data?.data?.cid) {
        window.open(`/container/preview/${data.data.cid}`, '_blank');
      } else {
        message.error('未绑定容器');
      }
    },
    code: ({ menu, data }) => {
      // console.log('edit', data);
      const nodeData = data?.data;
      if (!nodeData.cid) {
        message.error('请先绑定容器');
        return;
      }
      message.error('developing');
    },
    copy: ({ menu, data }) => {
      message.error('developing');
    },
    delete: ({ menu, data }) => {
      console.log('delete', data);
      const nodeData = data?.data;
      if (nodeData.root) {
        message.error('root node can not be deleted');
        return;
      }
      setNodes((nodes) => nodes.filter((item: any) => item.id !== data.id));
    },
    internalData: ({ menu, data }) => {
      message.error('developing');
    },
  });
  const { onNeedAdd, onAdd, onMouseMove, adding } = useAddNode();
  const onSave = useCallback(() => {
    panelStore.saveNodesEdges({
      nodes,
      edges,
    });
  }, [nodes, edges]);

  return (
    <ReactFlow
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
      onChange={(e) => {
        console.log('change', e);
      }}
      onChangeCapture={(e) => {
        console.log('change capture', e);
      }}
      onNodeDragStop={(e) => {
        console.log('drag stop', e);
      }}
      nodeTypes={nodeTypes}
      onMove={(e, viewport) => {
        // console.log('move', e, viewport)
      }}
      onContextMenu={(e) => {
        e.preventDefault();
      }}
      onPaneClick={(e) => {
        if (adding) {
          onAdd();
        }
      }}
      onNodeContextMenu={(e, node) => {
        console.log('context menu', e, node);
        onContextMenu(e as any, node);
      }}
      onMouseMove={(e) => onMouseMove(e)}
      onClick={(e) => {
        onClose();
      }}>
      <MiniMap />
      <Controls />
      <Background color='#000' />
      <Panel>{menuCom}</Panel>
      <Panel>
        <div className='flex gap-2'>
          <Button.Group>
            <Tooltip title='添加节点'>
              <Button
                icon={<PlusOutlined />}
                onClick={(e) => {
                  onNeedAdd({ id: 'flow' + generateId(), data: { label: '容器' }, type: 'container' }, e);
                }}></Button>
            </Tooltip>
            <Tooltip title='save'>
              <Button
                icon={<SaveOutlined />}
                onClick={() => {
                  onSave();
                }}></Button>
            </Tooltip>
            <Tooltip title='preview'>
              <Button
                icon={<CompassOutlined />}
                onClick={() => {
                  const id = panelStore.data?.id;
                  if (!id) {
                    message.error('ID is required');
                    return;
                  }
                  window.open(`/panel/deck/${id}`, '_blank');
                }}></Button>
            </Tooltip>
          </Button.Group>
        </div>
      </Panel>
      <NodeProperties />
    </ReactFlow>
  );
};

export default Flow;
