<script lang="ts" setup>
import type { WorkflowEdgeDto, WorkflowNodeDto } from '#/api/core';

import { computed } from 'vue';

import { Background } from '@vue-flow/background';
import { Controls } from '@vue-flow/controls';
import { useVueFlow, VueFlow } from '@vue-flow/core';
import { MiniMap } from '@vue-flow/minimap';
import { message } from 'ant-design-vue';

import { EdgeType, NodeType, updateNodeApi } from '#/api/core';

import '@vue-flow/core/dist/style.css';
import '@vue-flow/core/dist/theme-default.css';
import '@vue-flow/controls/dist/style.css';
import '@vue-flow/minimap/dist/style.css';

const props = defineProps<{
  definitionId: string;
  edges: WorkflowEdgeDto[];
  nodes: WorkflowNodeDto[];
}>();

const emit = defineEmits<{
  canvasClick: [];
  edgeClick: [edgeId: string];
  edgeDeleted: [edgeId: string];
  nodeClick: [nodeId: string];
  nodeDeleted: [nodeId: string];
}>();

const nodeTypeColors: Record<number, string> = {
  [NodeType.Start]: '#52c41a',
  [NodeType.End]: '#ff4d4f',
  [NodeType.Approval]: '#1890ff',
  [NodeType.Cc]: '#8c8c8c',
  [NodeType.Condition]: '#fa8c16',
  [NodeType.Parallel]: '#722ed1',
  [NodeType.SubProcess]: '#13c2c2',
};

const nodeTypeLabels: Record<number, string> = {
  [NodeType.Start]: '开始',
  [NodeType.End]: '结束',
  [NodeType.Approval]: '审批',
  [NodeType.Cc]: '抄送',
  [NodeType.Condition]: '条件',
  [NodeType.Parallel]: '并行',
  [NodeType.SubProcess]: '子流程',
};

const edgeTypeColors: Record<number, string> = {
  [EdgeType.Normal]: '#bfbfbf',
  [EdgeType.Approved]: '#52c41a',
  [EdgeType.Rejected]: '#ff4d4f',
};

const flowNodes = computed(() =>
  props.nodes.map((n) => ({
    id: n.id,
    type:
      n.nodeType === NodeType.Start || n.nodeType === NodeType.End
        ? 'circle'
        : 'custom',
    position: { x: n.positionX, y: n.positionY },
    data: {
      ...n,
      color: nodeTypeColors[n.nodeType] ?? '#1890ff',
      typeLabel: nodeTypeLabels[n.nodeType] ?? '未知',
    },
  })),
);

const flowEdges = computed(() =>
  props.edges.map((e) => ({
    id: e.id,
    source: e.sourceNodeId,
    target: e.targetNodeId,
    label: e.label ?? undefined,
    style: { stroke: edgeTypeColors[e.edgeType] ?? '#bfbfbf' },
    animated: e.edgeType === EdgeType.Approved,
  })),
);

const { onNodeClick, onEdgeClick, onPaneClick, onNodeDragStop } = useVueFlow();

onNodeClick(({ node }) => {
  emit('nodeClick', node.id);
});

onEdgeClick(({ edge }) => {
  emit('edgeClick', edge.id);
});

onPaneClick(() => {
  emit('canvasClick');
});

onNodeDragStop(async ({ node }) => {
  try {
    const originalNode = props.nodes.find((n) => n.id === node.id);
    if (!originalNode) return;
    await updateNodeApi(props.definitionId, node.id, {
      name: originalNode.name,
      config: originalNode.config ?? undefined,
      positionX: Math.round(node.position.x),
      positionY: Math.round(node.position.y),
    });
  } catch {
    message.error('保存节点位置失败');
  }
});
</script>

<template>
  <div class="h-full w-full">
    <VueFlow :edges="flowEdges" :nodes="flowNodes" fit-view-on-init>
      <template #node-custom="nodeProps">
        <div
          :style="{
            border: `2px solid ${nodeProps.data?.color ?? '#1890ff'}`,
            borderRadius: '8px',
            backgroundColor: '#fff',
            padding: '8px 16px',
            minWidth: '120px',
            textAlign: 'center',
            fontSize: '13px',
          }"
        >
          <div style="font-weight: 600">
            {{ nodeProps.data?.name ?? '未命名' }}
          </div>
          <div
            :style="{
              color: nodeProps.data?.color ?? '#999',
              fontSize: '11px',
            }"
          >
            {{ nodeProps.data?.typeLabel ?? '未知' }}
          </div>
        </div>
      </template>

      <template #node-circle="nodeProps">
        <div
          :style="{
            width: '48px',
            height: '48px',
            borderRadius: '50%',
            border: `2px solid ${nodeProps.data?.color ?? '#1890ff'}`,
            backgroundColor: '#fff',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            fontSize: '11px',
            fontWeight: 600,
          }"
        >
          {{ nodeProps.data?.name ?? '未命名' }}
        </div>
      </template>

      <Background />
      <Controls />
      <MiniMap />
    </VueFlow>
  </div>
</template>
