<template>
  <div class="panel-tab__content">
    <a-table
      :dataSource="elementListenersList"
      :columns="listenerColumns"
      size="small"
      bordered
      :pagination="false"
    >
      <template #bodyCell="{ column, record, index }">
        <template v-if="column.key === 'index'">
          {{ index + 1 }}
        </template>
        <template v-else-if="column.key === 'event'">
          {{ listenerEventTypeObject[record.event] }}
        </template>
        <template v-else-if="column.key === 'listenerType'">
          {{ listenerTypeObject[record.listenerType] }}
        </template>
        <template v-else-if="column.key === 'operation'">
          <a-button size="small" type="primary" @click="openListenerForm(record, index)">编辑</a-button>
          <a-divider type="vertical" />
          <a-button size="small" type="danger" @click="removeListener(record, index)">移除</a-button>
        </template>
      </template>
    </a-table>
    
    <div class="element-drawer__button_save">
      <a-button type="primary" size="small" @click="listenerSystemVisible = true">
        <template #icon><plus-outlined /></template>
        内置监听器
      </a-button>
      <a-button type="primary" size="small" @click="openListenerForm(null)">
        <template #icon><plus-outlined /></template>
        自定义监听器
      </a-button>
    </div>

    <!-- 监听器 编辑/创建 部分 -->
    <a-drawer
      v-model:open="listenerFormModelVisible"
      title="任务监听器"
      width="480px"
      :getContainer="false"
      :destroyOnClose="true"
    >
      <a-form
        :model="listenerForm"
        size="small"
        layout="vertical"
        ref="listenerFormRef"
        @submit.prevent
      >
        <a-form-item 
          name="event" 
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <template #label>
            <span>
              事件类型
              <a-tooltip placement="top">
                <template #title>
                  <div style="max-width: 400px">
                    create（创建）：当任务已经创建，并且所有任务参数都已经设置时触发。
                    <br />assignment（指派）：当任务已经指派给某人时触发。请注意：当流程执行到达用户任务时，
                    <br />在触发create事件之前，会首先触发assignment事件。这顺序看起来不太自然，
                    <br />但是有实际原因的：当收到create事件时，我们通常希望能看到任务的所有参数，包括办理人。
                    <br />complete（完成）：当任务已经完成，从运行时数据中删除前触发。
                    <br />delete（删除）：在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发。
                  </div>
                </template>
                <question-circle-outlined />
              </a-tooltip>
            </span>
          </template>
          <a-select v-model:value="listenerForm.event">
            <a-select-option 
              v-for="i in Object.keys(listenerEventTypeObject)" 
              :key="i" 
              :value="i"
            >
              {{ listenerEventTypeObject[i] }}
            </a-select-option>
          </a-select>
        </a-form-item>
        
        <a-form-item 
          label="监听器类型" 
          name="listenerType" 
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <template #label>
            <span>
              监听类型
              <a-tooltip placement="top">
                <template #title>
                  <div style="max-width: 400px">
                    class：需要调用的委托类。这个类必须实现org.flowable.engine.delegate.TaskListener接口。
                    <br />expression：表达式
                    <br />delegateExpression：代理表达式
                    <br />script：脚本
                  </div>
                </template>
                <question-circle-outlined />
              </a-tooltip>
            </span>
          </template>
          <a-select v-model:value="listenerForm.listenerType">
            <a-select-option 
              v-for="i in Object.keys(listenerTypeObject)" 
              :key="i" 
              :value="i"
            >
              {{ listenerTypeObject[i] }}
            </a-select-option>
          </a-select>
        </a-form-item>
        
        <a-form-item
          v-if="listenerForm.listenerType === 'classListener'"
          label="Java类"
          name="class"
          key="listener-class"
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerForm.class" allow-clear />
        </a-form-item>
        
        <a-form-item
          v-if="listenerForm.listenerType === 'expressionListener'"
          label="表达式"
          name="expression"
          key="listener-expression"
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerForm.expression" allow-clear />
        </a-form-item>
        
        <a-form-item
          v-if="listenerForm.listenerType === 'delegateExpressionListener'"
          label="代理表达式"
          name="delegateExpression"
          key="listener-delegate"
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerForm.delegateExpression" allow-clear />
        </a-form-item>
        
        <template v-if="listenerForm.listenerType === 'scriptListener'">
          <a-form-item
            label="脚本格式"
            name="scriptFormat"
            key="listener-script-format"
            :rules="[{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }]"
          >
            <a-input v-model:value="listenerForm.scriptFormat" allow-clear />
          </a-form-item>
          
          <a-form-item
            label="脚本类型"
            name="scriptType"
            key="listener-script-type"
            :rules="[{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }]"
          >
            <a-select v-model:value="listenerForm.scriptType">
              <a-select-option value="inlineScript">内联脚本</a-select-option>
              <a-select-option value="externalScript">外部脚本</a-select-option>
            </a-select>
          </a-form-item>
          
          <a-form-item
            v-if="listenerForm.scriptType === 'inlineScript'"
            label="脚本内容"
            name="value"
            key="listener-script"
            :rules="[{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }]"
          >
            <a-input v-model:value="listenerForm.value" allow-clear />
          </a-form-item>
          
          <a-form-item
            v-if="listenerForm.scriptType === 'externalScript'"
            label="资源地址"
            name="resource"
            key="listener-resource"
            :rules="[{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }]"
          >
            <a-input v-model:value="listenerForm.resource" allow-clear />
          </a-form-item>
        </template>

        <template v-if="listenerForm.event === 'timeout'">
          <a-form-item label="定时器类型" name="eventDefinitionType" key="eventDefinitionType">
            <a-select v-model:value="listenerForm.eventDefinitionType">
              <a-select-option value="date">日期</a-select-option>
              <a-select-option value="duration">持续时长</a-select-option>
              <a-select-option value="cycle">循环</a-select-option>
              <a-select-option value="null">无</a-select-option>
            </a-select>
          </a-form-item>
          
          <a-form-item
            v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
            label="定时器"
            name="eventTimeDefinitions"
            key="eventTimeDefinitions"
            :rules="[{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }]"
          >
            <a-input v-model:value="listenerForm.eventTimeDefinitions" allow-clear />
          </a-form-item>
        </template>
      </a-form>

      <a-divider />
      
      <p class="listener-filed__title">
        <span><menu-outlined />注入字段：</span>
        <a-button size="small" type="primary" @click="openListenerFieldForm(null)">添加字段</a-button>
      </p>
      
      <a-table
        :dataSource="fieldsListOfListener"
        :columns="fieldColumns"
        size="small"
        :scroll="{ y: 240 }"
        bordered
        :pagination="false"
      >
        <template #bodyCell="{ column, record, index }">
          <template v-if="column.key === 'index'">
            {{ index + 1 }}
          </template>
          <template v-else-if="column.key === 'fieldType'">
            {{ fieldTypeObject[record.fieldType] }}
          </template>
          <template v-else-if="column.key === 'value'">
            {{ record.string || record.expression }}
          </template>
          <template v-else-if="column.key === 'operation'">
            <a-button size="small" type="primary" @click="openListenerFieldForm(record, index)">编辑</a-button>
            <a-divider type="vertical" />
            <a-button size="small" type="danger" @click="removeListenerField(record, index)">移除</a-button>
          </template>
        </template>
      </a-table>

      <div class="element-drawer__button">
        <a-button size="small" @click="listenerFormModelVisible = false">取 消</a-button>
        <a-button size="small" type="primary" @click="saveListenerConfig">保 存</a-button>
      </div>
    </a-drawer>

    <!-- 注入字段 编辑/创建 部分 -->
    <a-modal
      v-model:open="listenerFieldFormModelVisible"
      title="字段配置"
      width="600px"
      :getContainer="false"
      :destroyOnClose="true"
      @cancel="listenerFieldFormModelVisible = false"
      @ok="saveListenerFiled"
    >
      <a-form
        :model="listenerFieldForm"
        layout="vertical"
        ref="listenerFieldFormRef"
        style="height: 136px"
        @submit.prevent
      >
        <a-form-item 
          label="字段名称：" 
          name="name" 
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerFieldForm.name" allow-clear />
        </a-form-item>
        
        <a-form-item 
          label="字段类型：" 
          name="fieldType" 
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-select v-model:value="listenerFieldForm.fieldType">
            <a-select-option 
              v-for="i in Object.keys(fieldTypeObject)" 
              :key="i" 
              :value="i"
            >
              {{ fieldTypeObject[i] }}
            </a-select-option>
          </a-select>
        </a-form-item>
        
        <a-form-item
          v-if="listenerFieldForm.fieldType === 'string'"
          label="字段值："
          name="string"
          key="field-string"
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerFieldForm.string" allow-clear />
        </a-form-item>
        
        <a-form-item
          v-if="listenerFieldForm.fieldType === 'expression'"
          label="表达式："
          name="expression"
          key="field-expression"
          :rules="[{ required: true, trigger: ['blur', 'change'] }]"
        >
          <a-input v-model:value="listenerFieldForm.expression" allow-clear />
        </a-form-item>
      </a-form>
      
      <template #footer>
        <a-button size="small" @click="listenerFieldFormModelVisible = false">取 消</a-button>
        <a-button size="small" type="primary" @click="saveListenerFiled">确 定</a-button>
      </template>
    </a-modal>

    <!-- 内置监听器 -->
    <a-drawer
      v-model:open="listenerSystemVisible"
      title="任务监听器"
      width="580px"
      :getContainer="false"
      :destroyOnClose="true"
    >
      <a-table
        :loading="loading"
        :dataSource="listenerList"
        :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
        :pagination="false"
      >
        <a-table-column key="selection" width="55" align="center">
          <template #default="{ record }">
            <a-checkbox :checked="selectedRowKeys.includes(record.id)" />
          </template>
        </a-table-column>
        <a-table-column title="名称" dataIndex="name" align="center" />
        <a-table-column title="类型" dataIndex="eventType" align="center" />
        <a-table-column title="监听类型" dataIndex="valueType" align="center">
          <template #default="{ record }">
            <span>{{ getDictLabel(dictData.sys_listener_value_type, record.valueType) }}</span>
          </template>
        </a-table-column>
        <a-table-column title="执行内容" dataIndex="value" align="center" ellipsis />
      </a-table>

      <a-pagination
        v-if="total > 0"
        :total="total"
        :current="queryParams.pageNum"
        :pageSize="queryParams.pageSize"
        show-less-items
        @change="handlePageChange"
        style="margin-top: 16px"
      />

      <div class="element-drawer__button">
        <a-button size="small" @click="listenerSystemVisible = false">取 消</a-button>
        <a-button 
          size="small" 
          type="primary" 
          :disabled="selectedRowKeys.length === 0" 
          @click="saveSystemListener"
        >
          保 存
        </a-button>
      </div>
    </a-drawer>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, watch, onMounted, nextTick } from 'vue'
import { Modal, message } from 'ant-design-vue'
import { 
  PlusOutlined, 
  QuestionCircleOutlined,
  MenuOutlined 
} from '@ant-design/icons-vue'
import { listListener } from "../api/listener"
import {
  changeListenerObject,
  createListenerObject,
  createSystemListenerObject,
  updateElementExtensions
} from "../common/bpmnUtils"
import { StrUtil } from "../common/StrUtil"

interface ListenerItem {
  event?: string
  listenerType?: string
  class?: string
  expression?: string
  delegateExpression?: string
  scriptFormat?: string
  scriptType?: string
  value?: string
  resource?: string
  fields?: any[]
  eventDefinitionType?: string
  eventTimeDefinitions?: string
  [key: string]: any
}

interface FieldItem {
  name?: string
  fieldType?: string
  string?: string
  expression?: string
  [key: string]: any
}

interface SystemListener {
  id?: string
  name?: string
  eventType?: string
  valueType?: string
  value?: string
  [key: string]: any
}

const props = defineProps<{
  id: string
}>()

const emit = defineEmits(['getTaskListenerCount'])

// 表格列定义
const listenerColumns = [
  {
    title: '序号',
    key: 'index',
    width: '50px'
  },
  {
    title: '类型',
    key: 'event',
    width: '60px',
    ellipsis: true
  },
  {
    title: '监听类型',
    key: 'listenerType',
    width: '85px',
    ellipsis: true
  },
  {
    title: '操作',
    key: 'operation'
  }
]

const fieldColumns = [
  {
    title: '序号',
    key: 'index',
    width: '50px'
  },
  {
    title: '字段名称',
    dataIndex: 'name',
    key: 'name',
    width: '80px'
  },
  {
    title: '字段类型',
    key: 'fieldType',
    width: '80px',
    ellipsis: true
  },
  {
    title: '值内容',
    key: 'value',
    width: '80px',
    ellipsis: true
  },
  {
    title: '操作',
    key: 'operation'
  }
]

// 响应式数据
const elementListenersList = ref<ListenerItem[]>([])
const listenerForm = reactive<ListenerItem>({})
const listenerFormModelVisible = ref(false)
const fieldsListOfListener = ref<FieldItem[]>([])
const bpmnElementListeners = ref<any[]>([])
const otherExtensionList = ref<any[]>([])
const listenerFieldForm = reactive<FieldItem>({})
const listenerFieldFormModelVisible = ref(false)
const editingListenerIndex = ref(-1)
const editingListenerFieldIndex = ref(-1)

const listenerList = ref<SystemListener[]>([])
const selectedRowKeys = ref<string[]>([])
const listenerSystemVisible = ref(false)
const loading = ref(true)
const total = ref(0)

const queryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  type: 1,
})

// 常量数据
const listenerTypeObject = {
  classListener: "Java 类",
  expressionListener: "表达式",
  delegateExpressionListener: "代理表达式",
  scriptListener: "脚本"
}

const listenerEventTypeObject = {
  create: "创建",
  assignment: "指派",
  complete: "完成",
  delete: "删除"
}

const fieldTypeObject = {
  string: "字符串",
  expression: "表达式"
}

// 字典数据（需要从外部获取）
const dictData = reactive({
  sys_listener_value_type: [] as any[],
  sys_listener_event_type: [] as any[]
})

// 假设这是从其他地方引入的 store
const modelerStore = {
  element: {} as any,
  modeling: {
    updateModdleProperties: (element: any, property: any, values: any) => {},
    updateProperties: (element: any, properties: any) => {}
  },
  moddle: {
    create: (type: string, values: any) => ({})
  }
}

// 表单引用
const listenerFormRef = ref()
const listenerFieldFormRef = ref()

// 监听 id 变化
watch(() => props.id, (newVal) => {
  if (StrUtil.isNotBlank(newVal)) {
    resetListenersList()
  }
}, { immediate: true })

// 重置监听器列表
const resetListenersList = () => {
  bpmnElementListeners.value =
    modelerStore.element.businessObject?.extensionElements?.values?.filter((ex: any) => 
      ex.$type === `flowable:TaskListener`) ?? []
  
  elementListenersList.value = bpmnElementListeners.value.map(listener => initListenerType(listener))
  emit('getTaskListenerCount', elementListenersList.value.length)
}

// 打开监听器表单
const openListenerForm = (listener: ListenerItem | null, index: number = -1) => {
  if (listener) {
    Object.assign(listenerForm, initListenerForm(listener))
    editingListenerIndex.value = index
  } else {
    Object.assign(listenerForm, {})
    editingListenerIndex.value = -1
  }
  
  if (listener && listener.fields) {
    fieldsListOfListener.value = listener.fields.map(field => ({
      ...field,
      fieldType: field.string ? "string" : "expression"
    }))
  } else {
    fieldsListOfListener.value = []
    listenerForm.fields = []
  }
  
  listenerFormModelVisible.value = true
  nextTick(() => {
    if (listenerFormRef.value) {
      listenerFormRef.value.clearValidate()
    }
  })
}

// 打开监听器字段表单
const openListenerFieldForm = (field: FieldItem | null, index: number = -1) => {
  if (field) {
    Object.assign(listenerFieldForm, JSON.parse(JSON.stringify(field)))
    editingListenerFieldIndex.value = index
  } else {
    Object.assign(listenerFieldForm, {})
    editingListenerFieldIndex.value = -1
  }
  
  listenerFieldFormModelVisible.value = true
  nextTick(() => {
    if (listenerFieldFormRef.value) {
      listenerFieldFormRef.value.clearValidate()
    }
  })
}

// 保存监听器字段
const saveListenerFiled = async () => {
  try {
    await listenerFieldFormRef.value.validate()
    
    if (editingListenerFieldIndex.value === -1) {
      fieldsListOfListener.value.push({ ...listenerFieldForm })
      listenerForm.fields!.push({ ...listenerFieldForm })
    } else {
      fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, { ...listenerFieldForm })
      listenerForm.fields!.splice(editingListenerFieldIndex.value, 1, { ...listenerFieldForm })
    }
    
    listenerFieldFormModelVisible.value = false
    Object.assign(listenerFieldForm, {})
  } catch (error) {
    console.log('验证失败', error)
  }
}

// 移除监听器字段
const removeListenerField = (field: FieldItem, index: number) => {
  Modal.confirm({
    title: '提示',
    content: '确认移除该字段吗？',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      fieldsListOfListener.value.splice(index, 1)
      listenerForm.fields!.splice(index, 1)
      message.success('移除成功')
    }
  })
}

// 移除监听器
const removeListener = (listener: ListenerItem, index: number) => {
  Modal.confirm({
    title: '提示',
    content: '确认移除该监听器吗？',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      bpmnElementListeners.value.splice(index, 1)
      elementListenersList.value.splice(index, 1)
      
      otherExtensionList.value = modelerStore.element.businessObject?.extensionElements?.values?.filter((ex: any) => 
        ex.$type !== `flowable:TaskListener`) ?? []
      
      updateElementExtensions(
        modelerStore.moddle, 
        modelerStore.modeling, 
        modelerStore.element, 
        otherExtensionList.value.concat(bpmnElementListeners.value)
      )
      
      emit('getTaskListenerCount', elementListenersList.value.length)
      message.success('移除成功')
    }
  })
}

// 保存监听器配置
const saveListenerConfig = async () => {
  try {
    await listenerFormRef.value.validate()
    
    const listenerObject = createListenerObject(modelerStore.moddle, listenerForm, false, "flowable")
    
    if (editingListenerIndex.value === -1) {
      bpmnElementListeners.value.push(listenerObject)
      elementListenersList.value.push({ ...listenerForm })
    } else {
      bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
      elementListenersList.value.splice(editingListenerIndex.value, 1, { ...listenerForm })
    }
    
    otherExtensionList.value = modelerStore.element.businessObject?.extensionElements?.values?.filter((ex: any) => 
      ex.$type !== `flowable:TaskListener`) ?? []
    
    updateElementExtensions(
      modelerStore.moddle, 
      modelerStore.modeling, 
      modelerStore.element, 
      otherExtensionList.value.concat(bpmnElementListeners.value)
    )
    
    emit('getTaskListenerCount', elementListenersList.value.length)
    listenerFormModelVisible.value = false
    Object.assign(listenerForm, {})
    message.success('保存成功')
  } catch (error) {
    console.log('验证失败', error)
  }
}

// 初始化监听器类型
const initListenerType = (listener: any): ListenerItem => {
  let listenerType
  if (listener.class) listenerType = "classListener"
  if (listener.expression) listenerType = "expressionListener"
  if (listener.delegateExpression) listenerType = "delegateExpressionListener"
  if (listener.script) listenerType = "scriptListener"
  
  return {
    ...JSON.parse(JSON.stringify(listener)),
    ...(listener.script ?? {}),
    listenerType: listenerType
  }
}

// 初始化监听器表单
const initListenerForm = (listener: ListenerItem): ListenerItem => {
  let result = { ...listener }
  
  if (listener.script) {
    result = {
      ...listener,
      ...listener.script,
      scriptType: listener.script.resource ? "externalScript" : "inlineScript"
    }
  }
  
  if (listener.event === "timeout" && listener.eventDefinitions) {
    if (listener.eventDefinitions.length) {
      let timeKey = ""
      for (const key in listener.eventDefinitions[0]) {
        if (key.indexOf("time") !== -1) {
          timeKey = key
          result.eventDefinitionType = key.replace("time", "").toLowerCase()
        }
      }
      result.eventTimeDefinitions = listener.eventDefinitions[0][timeKey].body
    }
  }
  
  return result
}

// 查询流程表达式列表
const getList = () => {
  loading.value = true
  listListener(queryParams).then((response: any) => {
    listenerList.value = response.rows
    total.value = response.total
    loading.value = false
  })
}

// 选择变化
const onSelectChange = (selectedKeys: string[]) => {
  selectedRowKeys.value = selectedKeys
}

// 分页变化
const handlePageChange = (page: number, pageSize: number) => {
  queryParams.pageNum = page
  queryParams.pageSize = pageSize
  getList()
}

// 保存内置监听器
const saveSystemListener = () => {
  if (selectedRowKeys.value.length > 0) {
    const selectedListeners = listenerList.value.filter(item => 
      selectedRowKeys.value.includes(item.id!)
    )
    
    selectedListeners.forEach(value => {
      const listenerObject = createSystemListenerObject(modelerStore.moddle, value, true, "flowable")
      bpmnElementListeners.value.push(listenerObject)
      elementListenersList.value.push(changeListenerObject(value))
    })
    
    otherExtensionList.value = modelerStore.element.businessObject?.extensionElements?.values?.filter((ex: any) => 
      ex.$type !== `flowable:TaskListener`) ?? []
    
    updateElementExtensions(
      modelerStore.moddle, 
      modelerStore.modeling, 
      modelerStore.element, 
      otherExtensionList.value.concat(bpmnElementListeners.value)
    )
    
    emit('getTaskListenerCount', elementListenersList.value.length)
    message.success('保存成功')
  }
  
  selectedRowKeys.value = []
  listenerSystemVisible.value = false
}

// 获取字典标签
const getDictLabel = (dictOptions: any[], value: any) => {
  const option = dictOptions.find(item => item.value === value)
  return option ? option.label : value
}

// 初始化
onMounted(() => {
  getList()
  // 这里需要初始化字典数据，根据实际情况获取
  dictData.sys_listener_value_type = [
    { value: '1', label: '类型1' },
    { value: '2', label: '类型2' }
  ]
  dictData.sys_listener_event_type = [
    { value: '1', label: '事件1' },
    { value: '2', label: '事件2' }
  ]
})
</script>

<style lang="scss">
.panel-tab__content {
  .element-drawer__button_save {
    margin-top: 10px;
    text-align: center;
    
    button {
      margin: 0 5px;
    }
  }
  
  .listener-filed__title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
  }
  
  .element-drawer__button {
    margin-top: 16px;
    text-align: right;
    
    button {
      margin-left: 8px;
    }
  }
}
</style>