<template>
  <div class="sino-page inbound-page">
    <el-card class="toolbar-card" shadow="never">
      <div class="toolbar">
        <el-input
          v-model="flowKeyword"
          placeholder="搜索流程编码 / 名称"
          clearable
          style="width: 260px"
          @keyup.enter="handleFlowSearch"
        />
        <el-button type="primary" @click="openCreateDialog">新建流程</el-button>
      </div>
    </el-card>

    <el-card class="flow-card" shadow="never">
      <div class="flow-layout">
        <!-- Left sidebar: flow list + node palette -->
        <div class="left-panel">
          <div class="panel-section flow-list">
            <div class="section-header">
              <span class="section-title">流程列表</span>
            </div>
            <el-table
              :data="pagedFlows"
              highlight-current-row
              size="small"
              @row-click="handleFlowRowClick"
              class="sino-table"
            >
              <el-table-column prop="flowCode" label="编码" show-overflow-tooltip />
              <el-table-column prop="flowName" label="名称" show-overflow-tooltip />
              <el-table-column prop="status" label="状态" width="70">
                <template #default="scope">
                  <el-tag :type="statusTagType(scope.row.status)" size="small">
                    {{ statusText(scope.row.status) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="version" label="版本" width="55">
                <template #default="scope">
                  <span>v{{ scope.row.version || 1 }}</span>
                </template>
              </el-table-column>
            </el-table>
            <div class="pagination-bar small">
              <el-pagination
                v-model:current-page="flowPage"
                v-model:page-size="flowPageSize"
                :total="totalFlowCount"
                :page-sizes="[10, 20, 50]"
                layout="total, prev, pager, next, sizes"
                @size-change="handleFlowSizeChange"
                @current-change="handleFlowPageChange"
              />
            </div>
          </div>

          <div class="panel-section node-palette">
            <div class="section-header">
              <span class="section-title">节点组件</span>
            </div>
            <div class="palette-grid">
              <div
                v-for="item in paletteNodes"
                :key="item.type"
                class="palette-item"
                :class="`palette-${item.type}`"
                draggable
                @click="addNode(item.type)"
                @dragstart="onDragStart($event, item.type)"
              >
                {{ item.label }}
              </div>
            </div>
          </div>
        </div>

        <!-- Center canvas -->
        <div class="canvas-area" @drop="onDrop" @dragover="onDragOver">
          <div class="flow-toolbar">
            <el-input
              v-model="form.flowCode"
              placeholder="流程编码"
              style="width: 160px"
              :disabled="isEdit"
            />
            <el-input
              v-model="form.flowName"
              placeholder="流程名称"
              style="width: 180px"
            />
            <el-button type="primary" @click="handleSave">保存</el-button>
            <el-button type="success" @click="handlePublish">发布</el-button>
            <el-button type="warning" @click="handleOffline">下线</el-button>
            <el-button type="danger" @click="handleDelete">删除</el-button>
            <el-button @click="resetCanvas">清空画布</el-button>
          </div>

          <div class="flow-canvas">
            <VueFlow
              v-model="elements"
              fit-view-on-init
              :default-zoom="1"
              @node-click="onNodeClick"
              @edge-click="onEdgeClick"
              @pane-click="onPaneClick"
            >
              <Background pattern-color="#aaa" :gap="16" />
              <Controls />
              <template #node-flowNode="nodeProps">
                <div
                  class="flow-node"
                  :class="[
                    `node-${nodeProps.data.nodeType}`,
                    { 'node-selected': nodeProps.selected },
                  ]"
                >
                  <Handle type="target" :position="Position.Top" />
                  <div class="node-icon">{{ nodeTypeIcon(nodeProps.data.nodeType) }}</div>
                  <div class="node-label">{{ nodeProps.label }}</div>
                  <Handle type="source" :position="Position.Bottom" />
                </div>
              </template>
            </VueFlow>
          </div>
        </div>

        <!-- Right config panel -->
        <div v-if="selectedNode || selectedEdge" class="right-panel">
          <template v-if="selectedNode">
            <div class="section-header">
              <span class="section-title">节点配置</span>
              <span class="node-type-tag">{{ nodeTypeLabel(selectedNode.data.nodeType) }}</span>
            </div>

            <el-form label-width="80px" class="config-form">
              <!-- receive -->
              <template v-if="selectedNode.data.nodeType === 'receive'">
                <el-form-item label="渠道类型">
                  <el-select v-model="selectedNode.data.config.channel_type" style="width: 100%">
                    <el-option label="企业微信" value="wecom" />
                    <el-option label="个人微信" value="wechat_personal" />
                  </el-select>
                </el-form-item>
              </template>

              <!-- intent -->
              <template v-if="selectedNode.data.nodeType === 'intent'">
                <el-form-item label="识别模式">
                  <el-select v-model="selectedNode.data.config.mode" style="width: 100%">
                    <el-option label="规则" value="rule" />
                    <el-option label="LLM" value="llm" />
                    <el-option label="混合" value="both" />
                  </el-select>
                </el-form-item>
                <el-form-item label="提示词" v-if="showIntentPrompt(selectedNode.data.config.mode)">
                  <el-input
                    v-model="selectedNode.data.config.prompt"
                    type="textarea"
                    :rows="6"
                    placeholder="请输入 LLM 识别提示词"
                  />
                </el-form-item>
              </template>

              <!-- condition -->
              <template v-if="selectedNode.data.nodeType === 'condition'">
                <el-form-item label="表达式">
                  <el-input
                    v-model="selectedNode.data.config.expression"
                    type="textarea"
                    :rows="4"
                    placeholder="例如：intent.intent == 'create_order'"
                  />
                </el-form-item>
                <div class="form-hint">提示：出边标签可填写 true / false 用于分支判断</div>
              </template>

              <!-- webhook -->
              <template v-if="selectedNode.data.nodeType === 'webhook'">
                <el-form-item label="请求地址">
                  <el-input v-model="selectedNode.data.config.url" placeholder="https://" />
                </el-form-item>
                <el-form-item label="请求方法">
                  <el-select v-model="selectedNode.data.config.method" style="width: 100%">
                    <el-option label="POST" value="POST" />
                    <el-option label="GET" value="GET" />
                    <el-option label="PUT" value="PUT" />
                  </el-select>
                </el-form-item>
              </template>

              <!-- reply -->
              <template v-if="selectedNode.data.nodeType === 'reply'">
                <el-form-item label="内容类型">
                  <el-select v-model="selectedNode.data.config.content.type" style="width: 100%">
                    <el-option label="文本" value="text" />
                    <el-option label="图片" value="image" />
                    <el-option label="图文卡片" value="news" />
                  </el-select>
                </el-form-item>
                <el-form-item label="内容">
                  <el-input
                    v-model="selectedNode.data.config.content.body"
                    type="textarea"
                    :rows="6"
                    placeholder="请输入回复内容"
                  />
                </el-form-item>
              </template>
            </el-form>
          </template>

          <template v-if="selectedEdge">
            <div class="section-header">
              <span class="section-title">边配置</span>
            </div>
            <el-form label-width="80px" class="config-form">
              <el-form-item label="标签">
                <el-input v-model="selectedEdge.label" placeholder="true / false" />
              </el-form-item>
            </el-form>
          </template>
        </div>
      </div>
    </el-card>

    <!-- 新建流程弹窗 -->
    <el-dialog v-model="createDialogVisible" title="新建流程" width="520px">
      <el-form :model="createForm" label-width="100px">
        <el-form-item label="流程编码">
          <el-input v-model="createForm.flowCode" placeholder="flow_xxx" />
        </el-form-item>
        <el-form-item label="流程名称">
          <el-input v-model="createForm.flowName" placeholder="新建入站流程" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="createDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmCreateFlow">确认</el-button>
      </template>
    </el-dialog>

    <!-- 流程详情抽屉 -->
    <el-drawer v-model="drawerVisible" title="流程详情" size="460px">
      <div v-if="selectedFlow" class="flow-detail">
        <div class="detail-item">
          <span class="detail-label">流程编码</span>
          <span class="detail-value">{{ selectedFlow.flowCode }}</span>
        </div>
        <div class="detail-item">
          <span class="detail-label">流程名称</span>
          <span class="detail-value">{{ selectedFlow.flowName }}</span>
        </div>
        <div class="detail-item">
          <span class="detail-label">状态</span>
          <el-tag :type="statusTagType(selectedFlow.status)" size="small">
            {{ statusText(selectedFlow.status) }}
          </el-tag>
        </div>
        <div class="detail-item">
          <span class="detail-label">版本</span>
          <span class="detail-value">v{{ selectedFlow.version || 1 }}</span>
        </div>
      </div>
      <template #footer>
        <div class="drawer-footer">
          <el-button @click="drawerVisible = false">关闭</el-button>
          <el-button type="primary" @click="editSelectedFlow">编辑画布</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { VueFlow, Handle, Position, useVueFlow } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import {
  listFlows,
  getFlow,
  saveFlow,
  updateFlow,
  publishFlow,
  offlineFlow,
  deleteFlow,
} from '@/api/inboundFlow'
import '@vue-flow/core/dist/style.css'
import '@vue-flow/core/dist/theme-default.css'

const { project } = useVueFlow()

interface FlowForm {
  flowCode: string
  flowName: string
}

const form = reactive<FlowForm>({
  flowCode: '',
  flowName: '',
})

const flows = ref<any[]>([])
const elements = ref<any[]>([])
const selectedNode = ref<any>(null)
const selectedEdge = ref<any>(null)
const isEdit = ref(false)

const flowKeyword = ref('')
const flowPage = ref(1)
const flowPageSize = ref(10)
const createDialogVisible = ref(false)
const drawerVisible = ref(false)
const selectedFlow = ref<any>(null)

const createForm = reactive({
  flowCode: '',
  flowName: '',
})

const paletteNodes = [
  { type: 'receive', label: '接收消息' },
  { type: 'intent', label: '意图识别' },
  { type: 'condition', label: '条件判断' },
  { type: 'webhook', label: 'Webhook' },
  { type: 'reply', label: '回复消息' },
]

const nodeTypeConfig: Record<string, () => any> = {
  receive: () => ({ channel_type: 'wecom' }),
  intent: () => ({ mode: 'llm', prompt: '' }),
  condition: () => ({ expression: '' }),
  webhook: () => ({ url: '', method: 'POST' }),
  reply: () => ({ content: { type: 'text', body: '' } }),
}

const nodeTypeLabels: Record<string, string> = {
  receive: '接收消息',
  intent: '意图识别',
  condition: '条件判断',
  webhook: 'Webhook',
  reply: '回复消息',
}

const nodeTypeIcons: Record<string, string> = {
  receive: '▶',
  intent: '💡',
  condition: '◆',
  webhook: '⚡',
  reply: '💬',
}

const filteredFlows = computed(() => {
  if (!flowKeyword.value) return flows.value
  const kw = flowKeyword.value.toLowerCase()
  return flows.value.filter(
    (f) =>
      (f.flowCode || '').toLowerCase().includes(kw) ||
      (f.flowName || '').toLowerCase().includes(kw)
  )
})

const totalFlowCount = computed(() => filteredFlows.value.length)

const pagedFlows = computed(() => {
  const start = (flowPage.value - 1) * flowPageSize.value
  return filteredFlows.value.slice(start, start + flowPageSize.value)
})

function nodeTypeLabel(type: string) {
  return nodeTypeLabels[type] || type
}

function nodeTypeIcon(type: string) {
  return nodeTypeIcons[type] || '•'
}

function statusText(status: number) {
  if (status === 1) return '已发布'
  if (status === 2) return '已下线'
  return '草稿'
}

function statusTagType(status: number) {
  if (status === 1) return 'success'
  if (status === 2) return 'warning'
  return 'info'
}

function showIntentPrompt(mode: string) {
  return mode === 'llm' || mode === 'both'
}

function createNodeId() {
  return `node_${Date.now()}_${Math.floor(Math.random() * 1000)}`
}

function createEdgeId(source: string, target: string) {
  return `e_${source}_${target}`
}

function getDefaultPosition() {
  const count = elements.value.filter((el) => !('source' in el)).length
  const row = Math.floor(count / 2)
  const col = count % 2
  return { x: 200 + col * 220, y: 80 + row * 140 }
}

function addNode(type: string, position?: { x: number; y: number }) {
  const id = createNodeId()
  const config = nodeTypeConfig[type]()
  elements.value.push({
    id,
    type: 'flowNode',
    label: nodeTypeLabels[type],
    position: position || getDefaultPosition(),
    data: { nodeType: type, config },
  })
}

function onDragStart(event: DragEvent, type: string) {
  if (event.dataTransfer) {
    event.dataTransfer.setData('application/vueflow-node', type)
    event.dataTransfer.effectAllowed = 'move'
  }
}

function onDragOver(event: DragEvent) {
  event.preventDefault()
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'move'
  }
}

function onDrop(event: DragEvent) {
  event.preventDefault()
  if (!event.dataTransfer) return
  const type = event.dataTransfer.getData('application/vueflow-node')
  if (!type) return

  const bounds = (event.currentTarget as HTMLElement).getBoundingClientRect()
  const position = project({
    x: event.clientX - bounds.left,
    y: event.clientY - bounds.top,
  })
  addNode(type, position)
}

function onNodeClick(event: any) {
  const node = event.node
  selectedEdge.value = null
  const found = elements.value.find((el) => el.id === node.id)
  selectedNode.value = found || node
}

function onEdgeClick(event: any) {
  const edge = event.edge
  selectedNode.value = null
  const found = elements.value.find((el) => el.id === edge.id)
  selectedEdge.value = found || edge
}

function onPaneClick() {
  selectedNode.value = null
  selectedEdge.value = null
}

function resetCanvas() {
  elements.value = []
  form.flowCode = ''
  form.flowName = ''
  isEdit.value = false
  selectedNode.value = null
  selectedEdge.value = null
}

function openCreateDialog() {
  createForm.flowCode = `flow_${Date.now()}`
  createForm.flowName = '新建入站流程'
  createDialogVisible.value = true
}

function confirmCreateFlow() {
  if (!createForm.flowCode.trim()) {
    ElMessage.warning('请输入流程编码')
    return
  }
  if (!createForm.flowName.trim()) {
    ElMessage.warning('请输入流程名称')
    return
  }
  resetCanvas()
  form.flowCode = createForm.flowCode
  form.flowName = createForm.flowName
  addNode('receive')
  addNode('intent')
  createDialogVisible.value = false
}

function handleFlowRowClick(row: any) {
  selectedFlow.value = row
  drawerVisible.value = true
}

function editSelectedFlow() {
  if (!selectedFlow.value) return
  loadFlow(selectedFlow.value.flowCode)
  drawerVisible.value = false
}

function handleFlowSearch() {
  flowPage.value = 1
}

function handleFlowPageChange(val: number) {
  flowPage.value = val
}

function handleFlowSizeChange(val: number) {
  flowPageSize.value = val
  flowPage.value = 1
}

function parseDefinitionJson(row: any): { nodes: any[]; edges: any[] } {
  if (!row.definitionJson) return { nodes: [], edges: [] }
  if (typeof row.definitionJson === 'string') {
    try {
      return JSON.parse(row.definitionJson)
    } catch {
      return { nodes: [], edges: [] }
    }
  }
  return row.definitionJson
}

async function loadFlow(flowCode: string) {
  try {
    const res: any = await getFlow(flowCode)
    const row = res.data
    if (!row) {
      ElMessage.warning('流程不存在')
      return
    }

    form.flowCode = row.flowCode
    form.flowName = row.flowName
    isEdit.value = true

    const definition = parseDefinitionJson(row)
    const nodes = (definition.nodes || []).map((n: any, index: number) => {
      const type = n.type || n.nodeType || 'receive'
      const config = n.config || {}
      return {
        id: n.id || createNodeId(),
        type: 'flowNode',
        label: nodeTypeLabels[type] || type,
        position: n.position || {
          x: 200 + (index % 3) * 220,
          y: 80 + Math.floor(index / 3) * 140,
        },
        data: { nodeType: type, config },
      }
    })

    const nodeIds = new Set(nodes.map((n) => n.id))
    const edges = (definition.edges || [])
      .filter((e: any) => nodeIds.has(e.source) && nodeIds.has(e.target))
      .map((e: any) => ({
        id: e.id || createEdgeId(e.source, e.target),
        source: e.source,
        target: e.target,
        label: e.label,
      }))

    elements.value = [...nodes, ...edges]
    selectedNode.value = null
    selectedEdge.value = null
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}

async function loadFlows() {
  try {
    const res: any = await listFlows()
    flows.value = res.data || []
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}

function buildPayload() {
  const nodes = elements.value
    .filter((el) => !('source' in el))
    .map((el) => ({
      id: el.id,
      type: el.data?.nodeType,
      config: el.data?.config || {},
      position: el.position,
    }))

  const edges = elements.value
    .filter((el) => 'source' in el)
    .map((el) => ({
      source: el.source,
      target: el.target,
      label: el.label,
    }))

  return {
    flowCode: form.flowCode,
    flowName: form.flowName,
    flowType: 'inbound',
    definitionJson: { nodes, edges },
  }
}

async function handleSave() {
  if (!form.flowCode.trim()) {
    ElMessage.warning('请输入流程编码')
    return
  }
  if (!form.flowName.trim()) {
    ElMessage.warning('请输入流程名称')
    return
  }

  try {
    const payload = buildPayload()
    if (isEdit.value) {
      await updateFlow(form.flowCode, payload)
      ElMessage.success('更新成功')
    } else {
      await saveFlow(payload)
      ElMessage.success('保存成功')
      isEdit.value = true
    }
    await loadFlows()
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}

async function handlePublish() {
  if (!form.flowCode.trim()) {
    ElMessage.warning('请先选择或保存流程')
    return
  }
  try {
    await publishFlow(form.flowCode)
    ElMessage.success('发布成功')
    await loadFlows()
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}

async function handleOffline() {
  if (!form.flowCode.trim()) {
    ElMessage.warning('请先选择流程')
    return
  }
  try {
    await offlineFlow(form.flowCode)
    ElMessage.success('已下线')
    await loadFlows()
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}

async function handleDelete() {
  if (!form.flowCode.trim()) {
    ElMessage.warning('请先选择流程')
    return
  }
  try {
    await ElMessageBox.confirm(`确定删除流程 ${form.flowCode} 吗？`, '提示', { type: 'warning' })
    await deleteFlow(form.flowCode)
    ElMessage.success('删除成功')
    resetCanvas()
    await loadFlows()
  } catch (e: any) {
    if (e !== 'cancel') {
      ElMessage.error(e.message)
    }
  }
}

onMounted(() => {
  loadFlows()
})
</script>

<style scoped>
.sino-page {
  --el-color-primary: #2563eb;
  --el-color-primary-light-3: #1d4ed8;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.inbound-page {
  height: calc(100vh - 112px);
}
.toolbar-card {
  border-radius: 12px;
  border: 1px solid #e2e8f0;
}
.flow-card {
  flex: 1;
  min-height: 0;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
}
.flow-card :deep(.el-card__body) {
  height: 100%;
  padding: 0;
}
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}
.flow-layout {
  display: flex;
  flex: 1;
  gap: 16px;
  height: 100%;
  min-height: 0;
}
.left-panel {
  width: 280px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
  padding: 16px;
}
.panel-section {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 12px;
  overflow: auto;
}
.flow-list {
  flex: 1;
  min-height: 0;
}
.node-palette {
  flex-shrink: 0;
}
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.section-title {
  font-weight: 600;
  font-size: 14px;
  color: #0f172a;
}
.palette-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.palette-item {
  padding: 10px 8px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  text-align: center;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
  user-select: none;
  color: #475569;
  background: #fff;
}
.palette-item:hover {
  border-color: #2563eb;
  color: #2563eb;
  background: #eff6ff;
}
.canvas-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-left: 1px solid #e2e8f0;
  border-right: 1px solid #e2e8f0;
  background: #fff;
}
.flow-toolbar {
  padding: 12px 16px;
  border-bottom: 1px solid #e2e8f0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.flow-canvas {
  flex: 1;
  min-height: 0;
}
.right-panel {
  width: 300px;
  background: #fff;
  padding: 16px;
  overflow: auto;
}
.config-form {
  margin-top: 12px;
}
.form-hint {
  font-size: 12px;
  color: #64748b;
  line-height: 1.5;
  padding: 0 0 12px 80px;
}
.node-type-tag {
  font-size: 12px;
  color: #2563eb;
  background: #eff6ff;
  padding: 2px 8px;
  border-radius: 4px;
}
.flow-node {
  padding: 10px 16px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  background: #fff;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 110px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06);
}
.flow-node.node-selected {
  border-color: #2563eb;
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
}
.node-icon {
  font-size: 16px;
}
.node-label {
  font-size: 13px;
  font-weight: 500;
}
.node-receive {
  border-left: 4px solid #22c55e;
}
.node-intent {
  border-left: 4px solid #f59e0b;
}
.node-condition {
  border-left: 4px solid #ef4444;
}
.node-webhook {
  border-left: 4px solid #2563eb;
}
.node-reply {
  border-left: 4px solid #94a3b8;
}
.pagination-bar {
  margin-top: 12px;
  display: flex;
  justify-content: flex-end;
}
.pagination-bar.small :deep(.el-pagination) {
  justify-content: flex-end;
}
.flow-detail {
  font-size: 14px;
}
.detail-item {
  margin-bottom: 16px;
}
.detail-label {
  display: block;
  color: #64748b;
  font-size: 13px;
  margin-bottom: 6px;
}
.detail-value {
  color: #0f172a;
  word-break: break-all;
}
.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
</style>
