<template>
  <Wrapper>
    <a-layout class="bg-transparent" style="background: transparent">
      <Header />
      <a-layout class="ks-layout-body">
        <div class="ks-model-builder-body">
          <div class="ks-model-builder-left">
            <PlatformCard
              ref="scenariosCardRef"
              @create="handleCreate"
              @select="handleSelect"
            />
            <NodesCard
              v-if="currentScenario && currentScenario.id >0"
              :scenario="currentScenario"
              @drag-item-start="handleDragStart"
              @drag-item-end="handleDragEnd"
            />
          </div>

          <div class="ks-model-builder-content" style="width: calc(100% - 250px);">
            <div class="ks-model-builder-actions">
              <a-space>
                <a-button v-if="graph && currentScenario" class="ks-model-builder-save" size="small" @click="handleSave">
                  <CheckOutlined />
                  <span>保存</span>
                </a-button>
              </a-space>
            </div>
            <!-- 画布容器，添加拖放事件 -->
            <div
              ref="canvas"
              class="ks-model-builder-canvas"
              @dragenter="handleDragEnter"
              @dragleave="handleDragLeave"
              @drop="handleDrop"
              @dragover.prevent
            ></div>
            <TeleportContainer />
          </div>
        </div>
      </a-layout>
    </a-layout>
  </Wrapper>
</template>

<script lang="ts">
import { defineComponent, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import { message } from 'ant-design-vue';
import { getTeleport } from '@antv/x6-vue-shape';
import { Graph, Node, type NodeProperties } from '@antv/x6';
import { CheckCircleOutlined, CheckOutlined, RollbackOutlined, SaveOutlined } from '@ant-design/icons-vue';
import { Wrapper } from '@/components/wrapper';
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
import Header from '../header.vue';

import type { PlatformWithComponents, Scenario } from './types';
import { createGraphTaskElement, createLineOptions, type GraphContainer, type GraphTaskElement, resolveGraph, useGraphCanvas } from '../graph';

import { registerScenarioElement } from './register';
import { createGraphScenarioElement, createGraphTaskElementFromScenario } from './utils';

import PlatformCard from './platform-card.vue';
import NodesCard from './nodes-card.vue';
import { saveScenario } from './api';

const TeleportContainer = defineComponent(getTeleport());

registerScenarioElement();

export default defineComponent({
  components: {
    PlatformCard,
    NodesCard,
    Wrapper,
    Header,
    SaveOutlined,
    CheckCircleOutlined,
    CheckOutlined,
    RollbackOutlined,
    TeleportContainer,
  },
  setup() {
    const canvas = ref<HTMLDivElement | null>(null);
    const graph = ref<Graph | null>(null);
    const currentZoom = ref<number>(1);
    const draggedNodeData = ref<PlatformWithComponents | null>(null);
    const isDraggingOver = ref(false);
    const currentScenarioEditing = ref<boolean>(false);
    const currentScenario = ref<Scenario | null>(null);
    const currentGraph = ref<GraphContainer | null>(null);
    const selectedModelNode = ref<Node<NodeProperties> | null>(null);
    const selectedNodeTaskElement = ref<GraphTaskElement | null>(null);
    const changed = ref<boolean>(false);
    const scenariosCardRef = ref<InstanceType<typeof PlatformCard> | null>(null);

    const {
      handleGraphEvent,
      createCanvas,
      zoomIn,
      zoomOut,
      fitToScreen,
      centerContent,
      resizeCanvas,
    } = useGraphCanvas();

    // 处理拖动开始
    const handleDragStart = (nm: PlatformWithComponents) => {
      draggedNodeData.value = nm;
    };

    // 处理拖动结束
    const handleDragEnd = () => {
      isDraggingOver.value = false;
    };

    // 处理拖动进入
    const handleDragEnter = (e: DragEvent) => {
      safePreventDefault(e);
      safeStopPropagation(e);
      isDraggingOver.value = true;
    };

    // 处理拖动离开
    const handleDragLeave = (e: DragEvent) => {
      safePreventDefault(e);
      safeStopPropagation(e);

      if (canvas.value && e.relatedTarget &&
        typeof e.relatedTarget === 'object' &&
        'nodeType' in e.relatedTarget) {
        // 使用 Element 类型而不是 x6 的 Node 类型
        if (!canvas.value.contains(e.relatedTarget as Element)) {
          isDraggingOver.value = false;
        }
      }
    };

    // 处理放置
    const handleDrop = (e: DragEvent) => {
      console.info('handleDrop', e);
      safePreventDefault(e);
      safeStopPropagation(e);
      isDraggingOver.value = false;
      currentScenarioEditing.value = false;

      if (!currentScenario.value) {
        message.error('请先选择场景.');
        return;
      }

      if (!graph.value || !canvas.value || !draggedNodeData.value) {
        message.error('无法放置节点,缺少必要数据');
        return;
      }

      try {
        // 获取拖动的数据
        const pwc = draggedNodeData.value as PlatformWithComponents;

        // if (!hasElements(graph.value as Graph)) {
        //   message.error('请先添加根节点.');
        //   return;
        // }

        // if (hasRootElementNode(graph.value as Graph)) {
        //   message.error('根节点已经存在.');
        //   return;
        // }

        // 计算相对于画布的位置（考虑缩放）
        const rect = canvas.value.getBoundingClientRect();
        const scale = currentZoom.value || 1;
        const x = (e.clientX - rect.left) / scale;
        const y = (e.clientY - rect.top) / scale;

        console.log('放置节点:', { ...pwc, x, y });

        // 创建节点数据
        const settingTaskElement: GraphTaskElement = createGraphTaskElementFromScenario(pwc, { x, y });
        // 创建节点
        const settingTaskNode = createGraphScenarioElement(settingTaskElement);
        console.info('create settingTaskNode: ', settingTaskElement, settingTaskNode);

        // 将节点添加到画布
        graph.value?.addNode(settingTaskNode as any);
        console.log('节点已添加到画布:', settingTaskNode.id);

        // 重置拖动数据
        draggedNodeData.value = null;
      } catch (error) {
        console.error('放置节点时出错:', error);
      }
    };

    const handleSelect = (scenario: Scenario) => {
      console.info('handleSelect', scenario);
      let nodeGraph: GraphContainer | null = null;
      try {
        nodeGraph = JSON.parse(scenario.communicationGraph as unknown as string) as unknown as GraphContainer;
      } catch (e: any) {
        console.error('parse error,cause:', e);
      }
      if (!nodeGraph) {
        nodeGraph = {
          nodes: [],
          edges: [],
        };
      }
      currentScenario.value = {
        ...scenario,
        graph: nodeGraph,
      };
      currentScenarioEditing.value = true;
      createElements();

    };

    const createElements = () => {
      nextTick(() => {
        try {
          graph.value?.clearCells();
        } catch (e: any) {
          console.error('clear cells error, cause:', e);
        }
        setTimeout(() => {
          if (currentScenario.value?.graph && graph.value) {
            if (currentScenario.value?.graph.nodes) {
              currentScenario.value?.graph.nodes.forEach(ele => {
                const node = createGraphScenarioElement(ele as GraphTaskElement);
                console.info('create node: ', ele);
                // 将节点添加到画布
                graph.value?.addNode(node as Node);
              });
            }
            if (currentScenario.value?.graph.edges) {
              // 然后添加所有边，确保包含桩点信息
              setTimeout(() => {
                currentScenario.value?.graph.edges.forEach(edgeData => {
                  graph.value?.addEdge({
                    ...edgeData,
                    ...createLineOptions(),
                  });
                });
              }, 100);  // 延迟一会儿,免得连线错位
            }
          }
        }, 100);
      });
    };

    const handleCreate = () => {
      currentScenario.value = {
        id: 0,
        name: null,
        description: null,
        communicationGraph: null,
        graph: {
          edges: [],
          nodes: [],
        }
      };
      currentGraph.value = {
        edges: [],
        nodes: [],
      };
      selectedModelNode.value = null;
      selectedNodeTaskElement.value = null;

      createElements();
    };

    // 初始化X6画布
    const initGraph = () => {
      if (!canvas.value) {
        console.error('画布容器不存在');
        return;
      }

      try {
        graph.value = createCanvas(canvas.value);
        console.log('画布初始化成功');
        createElements();

        // 监听缩放变化
        handleGraphEvent('scale', ({ sx }: { sx: number }) => {
          currentZoom.value = sx;
        });

        handleGraphEvent('blank:click', () => {
          selectedModelNode.value = null;
          selectedNodeTaskElement.value = null;
          currentScenarioEditing.value = null !== currentScenario.value;
        });

        handleGraphEvent('node:click', (args: any) => {
          const node = args.node as Node<NodeProperties>;
          const newElement = node.getData() as GraphTaskElement;

          selectedModelNode.value = node;
          selectedNodeTaskElement.value = JSON.parse(JSON.stringify(newElement || {})) as GraphTaskElement;
        });

        // 监听节点鼠标事件，显示/隐藏连接点
        handleGraphEvent('node:mouseenter', (_ctx: any) => {
        });

        handleGraphEvent('node:mouseleave', (_ctx: any) => {
        });
      } catch (error) {
        console.error('初始化画布失败:', error);
      }
    };

    // 监听窗口大小变化
    const handleResize = () => {
      nextTick(() => {
        resizeCanvas();
      });
    };

    const init = () => {
      console.info('init');
      nextTick(() => {
        initGraph();
        window.addEventListener('resize', handleResize);
        console.log('节点挂载完成');
      });
    };

    const handleUpdateElement = (element: GraphTaskElement) => {
      // 更新选中的节点数据
      if (selectedModelNode.value) {
        selectedModelNode.value.replaceData(element);
      }
      console.info('handleUpdateElement', element);
      // 更新本地引用
      selectedNodeTaskElement.value = element;
      changed.value = true;
    };

    const handleSave = () => {
      const graphData: GraphContainer = resolveGraph(graph.value as Graph);
      console.info('handleSave', graphData);
      if (!currentScenario.value) {
        message.error('当前决策树不存在');
        return;
      }
      const newScenario: Scenario = {
        ...currentScenario.value,
        graph: graphData,
        communicationGraph: JSON.stringify(graphData),
      };
      if (!newScenario.name) {
        message.error('场景名称不能为空.');
        return;
      }
      let res = null;
      if (currentScenario.value.id > 0) {
        res = saveScenario(newScenario);
      } else {
        res = saveScenario(newScenario);
      }
      res.then(r => {
        if (r.code === 200) {
          scenariosCardRef.value?.refresh();
          message.success(r.msg ?? '操作成功.');
        } else {
          message.error(r.msg ?? '操作失败.');
        }
      });
    };

    // 初始化
    onMounted(() => {
      init();
    });

    // 清理
    onBeforeUnmount(() => {
      window.removeEventListener('resize', handleResize);
      if (graph.value) {
        try {
          graph.value.clearCells();
        } catch (error) {
          console.warn('销毁画布时出错:', error);
        }
        graph.value = null;
        console.log('画布已销毁');
      }
    });

    return {
      scenariosCardRef,
      handleCreate,
      currentScenarioEditing,
      currentScenario,
      currentGraph,
      selectedNodeTaskElement,
      selectedModelNode,
      graph,
      canvas,
      zoomIn,
      zoomOut,
      fitToScreen,
      centerContent,
      handleDragStart,
      handleDragEnd,
      handleDragEnter,
      handleDragLeave,
      handleDrop,
      isDraggingOver,
      handleSave,
      handleUpdateElement,
      handleSelect,
    };
  },
});
</script>