<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import Modeler from 'bpmn-js/lib/Modeler';
import { Button, Divider, message, Popconfirm, Space } from 'ant-design-vue';

// Camunda 扩展模块
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json';

// 属性面板 - 使用最新版本
import {
  BpmnPropertiesPanelModule,
  BpmnPropertiesProviderModule,
  CamundaPlatformPropertiesProviderModule,
} from 'bpmn-js-properties-panel';

// 中文翻译
import { customTranslate } from './translate/zh-CN';

// 样式文件 - 按照官方文档顺序引入
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
// 属性面板样式 - 需要先安装 @bpmn-io/properties-panel
import '@bpmn-io/properties-panel/dist/assets/properties-panel.css';

defineOptions({ name: 'ProcessDesign' });

const containerRef = ref<HTMLDivElement>();
const propertiesPanelRef = ref<HTMLDivElement>();
let bpmnModeler: Modeler | null = null;

// 默认的 BPMN XML 模板（包含 Camunda 命名空间）
const defaultBpmnXML = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" 
  xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" 
  xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" 
  xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
  xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
  id="Definitions_1" 
  targetNamespace="http://bpmn.io/schema/bpmn">
  <bpmn:process id="Process_1" name="业务流程" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1" name="流程开始"/>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="Shape_StartEvent_1" bpmnElement="StartEvent_1">
        <dc:Bounds x="173" y="102" width="36" height="36"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds x="166" y="145" width="52" height="14"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>`;

// 初始化 BPMN 建模器
function initBpmnModeler() {
  if (!containerRef.value || !propertiesPanelRef.value) return;

  bpmnModeler = new Modeler({
    container: containerRef.value,
    // 添加属性面板
    propertiesPanel: {
      parent: propertiesPanelRef.value,
    },
    // 添加额外的模块
    additionalModules: [
      BpmnPropertiesPanelModule,
      BpmnPropertiesProviderModule,
      CamundaPlatformPropertiesProviderModule,
      // 中文翻译模块
      {
        translate: ['value', customTranslate]
      }
    ],
    // 添加 Camunda 扩展
    moddleExtensions: {
      camunda: camundaModdleDescriptor,
    },
  });

  // 加载默认 BPMN 图
  bpmnModeler.importXML(defaultBpmnXML).then(() => {
    const canvas = bpmnModeler!.get('canvas');
    canvas.zoom('fit-viewport');
    message.success('流程图加载成功');
  }).catch((err: any) => {
    console.error('加载 BPMN 图失败:', err);
    message.error('流程图加载失败');
  });
}

// 导出 BPMN XML
async function exportXML() {
  if (!bpmnModeler) return;
  
  try {
    const { xml } = await bpmnModeler.saveXML({ format: true });
    console.log('BPMN XML:', xml);
    message.success('导出成功，请查看控制台');
    return xml;
  } catch (err) {
    console.error('导出 XML 失败:', err);
    message.error('导出失败');
  }
}

// 导出 SVG
async function exportSVG() {
  if (!bpmnModeler) return;
  
  try {
    const { svg } = await bpmnModeler.saveSVG();
    console.log('BPMN SVG:', svg);
    
    // 下载 SVG
    const blob = new Blob([svg], { type: 'image/svg+xml' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'process-diagram.svg';
    link.click();
    URL.revokeObjectURL(url);
    
    message.success('SVG 导出成功');
  } catch (err) {
    console.error('导出 SVG 失败:', err);
    message.error('导出失败');
  }
}

// 撤销
function undo() {
  if (!bpmnModeler) return;
  const commandStack = bpmnModeler.get('commandStack');
  if (commandStack.canUndo()) {
    commandStack.undo();
  }
}

// 重做
function redo() {
  if (!bpmnModeler) return;
  const commandStack = bpmnModeler.get('commandStack');
  if (commandStack.canRedo()) {
    commandStack.redo();
  }
}

// 缩放
function zoomIn() {
  if (!bpmnModeler) return;
  const canvas = bpmnModeler.get('canvas');
  canvas.zoom(canvas.zoom() + 0.1);
}

function zoomOut() {
  if (!bpmnModeler) return;
  const canvas = bpmnModeler.get('canvas');
  canvas.zoom(canvas.zoom() - 0.1);
}

function zoomReset() {
  if (!bpmnModeler) return;
  const canvas = bpmnModeler.get('canvas');
  canvas.zoom('fit-viewport');
}

// 清空画布
function clearDiagram() {
  if (!bpmnModeler) return;
  bpmnModeler.importXML(defaultBpmnXML).then(() => {
    const canvas = bpmnModeler!.get('canvas');
    canvas.zoom('fit-viewport');
    message.success('画布已清空');
  });
}

onMounted(() => {
  initBpmnModeler();
});

onUnmounted(() => {
  if (bpmnModeler) {
    bpmnModeler.destroy();
    bpmnModeler = null;
  }
});
</script>

<template>
  <div class="process-design-container">
    <!-- 工具栏 -->
    <div class="toolbar">
      <Space>
        <Button type="primary" @click="exportXML">导出 XML</Button>
        <Button @click="exportSVG">导出 SVG</Button>
        
        <Divider type="vertical" />
        
        <Button @click="undo">撤销</Button>
        <Button @click="redo">重做</Button>
        
        <Divider type="vertical" />
        
        <Button @click="zoomIn">放大</Button>
        <Button @click="zoomOut">缩小</Button>
        <Button @click="zoomReset">适应窗口</Button>
        
        <Divider type="vertical" />
        
        <Popconfirm
          title="确定要清空画布吗？"
          ok-text="确定"
          cancel-text="取消"
          @confirm="clearDiagram"
        >
          <Button danger>清空画布</Button>
        </Popconfirm>
      </Space>
    </div>
    
    <!-- 主内容区：画布 + 属性面板 -->
    <div class="content-container">
      <!-- BPMN 画布容器 -->
      <div ref="containerRef" class="bpmn-container"></div>
      
      <!-- Camunda 属性面板 -->
      <div ref="propertiesPanelRef" class="properties-panel-container"></div>
    </div>
  </div>
</template>

<style scoped>
.process-design-container {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 100px);
  background: var(--bg-color, #f0f2f5);
}

.toolbar {
  padding: 12px 16px;
  background: var(--component-background, #ffffff);
  border-bottom: 1px solid var(--border-color, #e8e8e8);
  flex-shrink: 0;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.content-container {
  display: flex;
  flex: 1;
  overflow: hidden;
  background: var(--bg-color, #f0f2f5);
}

.bpmn-container {
  flex: 1;
  background: var(--component-background, #ffffff);
  overflow: hidden;
  position: relative;
  margin: 8px 0 8px 8px;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.properties-panel-container {
  width: 280px;
  min-width: 280px;
  max-width: 280px;
  background: var(--component-background, #ffffff);
  border-left: 1px solid var(--border-color, #e8e8e8);
  overflow: hidden;
  flex-shrink: 0;
  margin: 8px 8px 8px 0;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

/* 图标样式 - 使用 Iconify */
.i-lucide\:download,
.i-lucide\:image,
.i-lucide\:undo,
.i-lucide\:redo,
.i-lucide\:zoom-in,
.i-lucide\:zoom-out,
.i-lucide\:maximize,
.i-lucide\:trash-2 {
  display: inline-block;
  width: 1em;
  height: 1em;
}
</style>

<style>
/* 
  属性面板样式增强 - 适配 Ant Design 主题
  官方 CSS 已引入，这里只做主题色调整
*/

/* 属性面板容器适配 */
.process-design-container .bio-properties-panel {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif !important;
}

/* 调整焦点颜色为 Ant Design 主题色 */
.process-design-container .bio-properties-panel input:focus,
.process-design-container .bio-properties-panel textarea:focus,
.process-design-container .bio-properties-panel select:focus {
  border-color: var(--ant-primary-color, #1890ff) !important;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2) !important;
}

/* 按钮主题色调整 */
.process-design-container .bio-properties-panel button:not(.bio-properties-panel-remove-entry):hover {
  border-color: var(--ant-primary-color, #1890ff);
  color: var(--ant-primary-color, #1890ff);
}
</style>

