<template>
  <div class="app-container">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>流程执行</span>
        </div>
      </template>

      <el-tabs v-model="activeTab">
        <el-tab-pane label="发起流程" name="start" lazy>
          <div v-if="loadingDefinitions" v-loading="true" style="height: 200px;" />
          <el-empty v-else-if="definitionList.length === 0" description="暂无可用的流程" />
          <div v-else class="definition-list">
            <el-card v-for="def in definitionList" :key="def.id" class="definition-card" shadow="hover">
              <div class="def-header">
                <el-tag type="success" size="small">已发布</el-tag>
                <span class="def-name">{{ def.name }}</span>
              </div>
              <div class="def-info">
                <p><strong>编码：</strong>{{ def.code }}</p>
                <p v-if="def.category"><strong>分类：</strong>{{ def.category }}</p>
                <p v-if="def.description"><strong>描述：</strong>{{ def.description }}</p>
              </div>
              <div class="def-actions">
                <el-button type="primary" size="small" @click="handleStart(def)">发起流程</el-button>
                <el-button type="info" size="small" :icon="View" @click="openPreview(def)">查看详情</el-button>
              </div>
            </el-card>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <el-dialog v-model="startDialogVisible" title="发起流程" width="640px">
      <el-form ref="startFormRef" :model="startForm" :rules="startFormRules" label-width="80px">
        <el-form-item v-show="false"><el-input v-model="startForm.processDefinitionId" /></el-form-item>
        <el-form-item label="流程名称"><el-input v-model="startForm.definitionName" disabled /></el-form-item>
        <el-form-item label="标题" prop="title"><el-input v-model="startForm.title" placeholder="请输入流程标题" /></el-form-item>
        <el-form-item label="表单数据">
          <FlowFormFields v-if="hasFormFields" v-model="dynamicFormData" :definition="selectedDefinition" />
          <el-input v-else v-model="startForm.formData" type="textarea" :rows="4" placeholder="请输入表单数据，格式：每行一个字段，如 amount=1000" />
        </el-form-item>
        <!-- TODO: 接入OSS后重新启用附件功能 -->
        <el-form-item v-if="false" label="附件">
          <el-upload v-model:file-list="fileUpload.attachmentList" action="#" :http-request="fileUpload.handleUpload" :before-upload="beforeFileUpload" :before-remove="() => true" :limit="5" multiple>
            <el-button type="primary" size="small">上传附件</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="startDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="submitStart">确认发起</el-button>
      </template>
    </el-dialog>

    <!-- 流程详情预览弹窗 -->
    <el-dialog v-model="previewVisible" title="流程详情" width="640px">
      <div v-if="previewDefinition" class="preview-content">
        <div class="preview-section">
          <h4>基本信息</h4>
          <p><strong>流程名称：</strong>{{ previewDefinition.name }}</p>
          <p><strong>流程编码：</strong>{{ previewDefinition.code }}</p>
          <p v-if="previewDefinition.category"><strong>分类：</strong>{{ previewDefinition.category }}</p>
          <p v-if="previewDefinition.description"><strong>描述：</strong>{{ previewDefinition.description }}</p>
        </div>

        <div v-if="previewFormFields.length > 0" class="preview-section">
          <h4>表单字段</h4>
          <el-table :data="previewFormFields" size="small" border>
            <el-table-column prop="label" label="显示名" min-width="120" />
            <el-table-column prop="name" label="字段名" min-width="120" />
            <el-table-column label="类型" width="90">
              <template #default="{ row }">
                {{ fieldTypeText(row.type) }}
              </template>
            </el-table-column>
            <el-table-column label="必填" width="70" align="center">
              <template #default="{ row }">
                <el-checkbox v-model="row.required" disabled />
              </template>
            </el-table-column>
          </el-table>
        </div>

        <div v-if="previewApprovalNodes.length > 0" class="preview-section">
          <h4>审批节点</h4>
          <el-timeline>
            <el-timeline-item
              v-for="(node, index) in previewApprovalNodes"
              :key="node.id"
              :type="node.type === 'cc-node' ? 'info' : 'primary'"
            >
              <div class="preview-node">
                <span class="preview-node-index">{{ index + 1 }}</span>
                <span class="preview-node-name">{{ node.name }}</span>
                <el-tag size="small" :type="node.type === 'cc-node' ? 'info' : 'warning'">
                  {{ node.type === 'cc-node' ? '抄送' : '审批' }}
                </el-tag>
              </div>
            </el-timeline-item>
          </el-timeline>
        </div>
      </div>
      <template #footer>
        <el-button @click="previewVisible = false">关闭</el-button>
        <el-button type="primary" @click="handleStartFromPreview">发起流程</el-button>
      </template>
    </el-dialog>

    <InstanceDetail v-model="detailVisible" :instance-id="currentInstanceId" />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { View } from '@element-plus/icons-vue'
import { listEnabled } from '@/api/flow/definition'
import { startInstance } from '@/api/flow/instance'
import { beforeFileUpload, collectAttachmentUrls } from '@/utils/file'
import { useFileUpload } from '@/composables/useFileUpload'
import type { FlowDefinition, FormField } from '@/types/flow'
import InstanceDetail from './InstanceDetail.vue'
import FlowFormFields from '@/components/FlowFormFields/index.vue'

const activeTab = ref('start')
const loadingDefinitions = ref(false)
const submitting = ref(false)
const definitionList = ref<FlowDefinition[]>([])
const startDialogVisible = ref(false)
const startFormRef = ref<FormInstance>()
const startForm = ref({ processDefinitionId: 0 as number, definitionName: '', title: '', formData: '' })
const dynamicFormData = ref<Record<string, unknown>>({})
const selectedDefinition = ref<FlowDefinition | null>(null)
const fileUpload = reactive(useFileUpload())
const startFormRules: FormRules = { title: [{ required: true, message: '请输入标题', trigger: 'blur' }] }
const hasFormFields = computed(() => {
  const s = selectedDefinition.value?.formSchema
  if (!s) return false
  try { const a = JSON.parse(s); return Array.isArray(a) && a.length > 0 } catch { return false }
})
const detailVisible = ref(false)
const currentInstanceId = ref(0)
const previewVisible = ref(false)
const previewDefinition = ref<FlowDefinition | null>(null)

const previewFormFields = computed<FormField[]>(() => {
  const schema = previewDefinition.value?.formSchema
  if (!schema) return []
  try {
    const parsed = JSON.parse(schema)
    return Array.isArray(parsed) ? parsed : []
  } catch {
    return []
  }
})

interface PreviewNode {
  id: string
  type: string
  name: string
}

const previewApprovalNodes = computed<PreviewNode[]>(() => {
  const flowJson = previewDefinition.value?.flowJson
  if (!flowJson) return []
  try {
    const model = JSON.parse(flowJson)
    const nodes = Array.isArray(model?.nodes) ? model.nodes : []
    return nodes.filter((n: any) => n?.type === 'approval-node' || n?.type === 'cc-node')
      .map((n: any) => ({ id: n.id, type: n.type, name: n.name || '未命名节点' }))
  } catch {
    return []
  }
})

function fieldTypeText(type?: string): string {
  const map: Record<string, string> = {
    text: '文本',
    number: '数字',
    date: '日期',
    select: '下拉',
    textarea: '多行文本'
  }
  return map[type || ''] || type || '-'
}

function openPreview(def: FlowDefinition) {
  previewDefinition.value = def
  previewVisible.value = true
}

function handleStartFromPreview() {
  if (!previewDefinition.value) return
  previewVisible.value = false
  handleStart(previewDefinition.value)
}

async function loadDefinitions() {
  loadingDefinitions.value = true
  try { definitionList.value = await listEnabled() } finally { loadingDefinitions.value = false }
}

function handleStart(def: FlowDefinition) {
  startForm.value.processDefinitionId = def.id; startForm.value.definitionName = def.name
  startForm.value.title = ''; startForm.value.formData = ''; dynamicFormData.value = {}
  selectedDefinition.value = def; fileUpload.resetFileUpload()
  startDialogVisible.value = true
}

async function submitStart() {
  const v = await startFormRef.value?.validate().catch(() => false)
  if (!v) return
  submitting.value = true
  try {
    let fd: Record<string, unknown> | undefined
    if (selectedDefinition.value?.formSchema) { fd = { ...dynamicFormData.value } }
    else if (startForm.value.formData.trim()) {
      fd = {}
      startForm.value.formData.split('\n').forEach(l => {
        const i = l.indexOf('='); if (i > 0) {
          const k = l.substring(0, i).trim(), val = l.substring(i + 1).trim()
          if (k) { const n = Number(val); fd![k] = !isNaN(n) && val !== '' ? n : val }
        }
      })
    }
    const au = fileUpload.attachmentList.length > 0 ? collectAttachmentUrls(fileUpload.attachmentList) : undefined
    await startInstance(startForm.value.processDefinitionId, startForm.value.title || undefined, fd, au)
    ElMessage.success('流程发起成功'); startDialogVisible.value = false
  } finally { submitting.value = false }
}

onMounted(loadDefinitions)
</script>

<style scoped>
.card-header { display: flex; justify-content: space-between; align-items: center; }
.definition-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.definition-card { cursor: default; }
.def-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.def-name { font-size: 16px; font-weight: bold; color: #303133; }
.def-info { font-size: 13px; color: #606266; margin-bottom: 12px; }
.def-info p { margin: 4px 0; }
.def-actions { display: flex; gap: 8px; }
.preview-content { max-height: 60vh; overflow-y: auto; padding-right: 8px; }
.preview-section { margin-bottom: 20px; }
.preview-section h4 { margin: 0 0 12px 0; font-size: 15px; color: #303133; border-left: 4px solid #409eff; padding-left: 8px; }
.preview-section p { margin: 6px 0; color: #606266; font-size: 14px; }
.preview-node { display: flex; align-items: center; gap: 8px; }
.preview-node-index { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background-color: #f0f2f5; color: #606266; font-size: 12px; }
.preview-node-name { font-size: 14px; color: #303133; }
</style>
