<template>
  <div class="flow-form-fields">
    <div v-if="fields.length === 0" class="empty-tip">
      <el-text type="info">该流程未配置表单字段，可直接发起。</el-text>
    </div>
    <div v-else>
      <div class="form-actions">
        <el-button type="primary" size="small" plain @click="handleDownloadTemplate">下载 Excel 模板</el-button>
        <el-upload
          action="#"
          :show-file-list="false"
          :http-request="handleExcelUpload"
          :before-upload="beforeExcelUpload"
          accept=".xlsx,.xls"
          style="display: inline-block; margin-left: 8px;"
        >
          <el-button type="success" size="small" plain>上传 Excel 自动填充</el-button>
        </el-upload>
      </div>

      <div class="field-list">
        <div
          v-for="field in fields"
          :key="field.name"
          class="field-row"
          :class="{ 'field-row-full': field.type === 'textarea' }"
        >
          <label class="field-label">
            <span>{{ field.label }}</span>
            <span v-if="field.required" class="required-star">*</span>
          </label>
          <div class="field-control">
            <el-input
              v-if="!field.type || field.type === 'text'"
              v-model="formData[field.name]"
              :placeholder="`请输入${field.label}`"
              clearable
              size="large"
            />
            <el-input
              v-else-if="field.type === 'textarea'"
              v-model="formData[field.name]"
              type="textarea"
              :rows="4"
              :placeholder="`请输入${field.label}`"
              clearable
              size="large"
            />
            <el-input-number
              v-else-if="field.type === 'number'"
              v-model="formData[field.name]"
              style="width: 100%;"
              :placeholder="`请输入${field.label}`"
              controls-position="right"
              size="large"
            />
            <el-date-picker
              v-else-if="field.type === 'date'"
              v-model="formData[field.name]"
              type="date"
              style="width: 100%;"
              :placeholder="`请选择${field.label}`"
              value-format="YYYY-MM-DD"
              size="large"
            />
            <el-select
              v-else-if="field.type === 'select'"
              v-model="formData[field.name]"
              style="width: 100%;"
              :multiple="field.multiple"
              :placeholder="`请选择${field.label}`"
              clearable
              collapse-tags
              collapse-tags-tooltip
              size="large"
            >
              <el-option
                v-for="opt in normalizeOptions(field.options)"
                :key="String(opt.value)"
                :label="opt.label"
                :value="opt.value"
              />
            </el-select>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import type { FormField, FormFieldOption, FlowDefinition } from '@/types/flow'
import { downloadTemplate as downloadFlowTemplate } from '@/api/flow/import'
import request from '@/api/request'

const props = defineProps<{
  definition: FlowDefinition | null | undefined
}>()

const formData = defineModel<Record<string, unknown>>('modelValue', { default: () => ({}) })

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

// 切换流程定义时重置数据；同时为多选下拉设置数组默认值
watch(() => props.definition?.id, (newId, oldId) => {
  if (newId === oldId) return
  // 保留已有数据（如回退后补充材料场景）
  if (Object.keys(formData.value || {}).length > 0) return
  formData.value = {}
  for (const field of fields.value) {
    if (field.type === 'select' && field.multiple) {
      formData.value[field.name] = []
    }
  }
}, { immediate: true })

function normalizeOptions(options?: FormFieldOption[] | string[]): FormFieldOption[] {
  if (!options || !Array.isArray(options)) return []
  return options.map((opt: any) => {
    if (typeof opt === 'string') {
      return { label: opt, value: opt }
    }
    return { label: String(opt.label ?? opt.value), value: opt.value }
  })
}

function validate(): boolean {
  for (const field of fields.value) {
    if (!field.required) continue
    const value = formData.value[field.name]
    if (field.type === 'select' && field.multiple) {
      if (!Array.isArray(value) || value.length === 0) {
        ElMessage.warning(`请选择 ${field.label}`)
        return false
      }
    } else {
      if (value === undefined || value === null || String(value).trim() === '') {
        ElMessage.warning(`请填写 ${field.label}`)
        return false
      }
    }
  }
  return true
}

async function handleDownloadTemplate() {
  if (!props.definition?.id) return
  try {
    await downloadFlowTemplate(props.definition.id)
  } catch (e: any) {
    ElMessage.error(e?.message || '模板下载失败')
  }
}

function beforeExcelUpload(file: File): boolean {
  const ext = file.name.split('.').pop()?.toLowerCase()
  if (!ext || !['xlsx', 'xls'].includes(ext)) {
    ElMessage.warning('请上传 Excel 文件')
    return false
  }
  if (file.size > 10 * 1024 * 1024) {
    ElMessage.warning('文件大小不能超过 10MB')
    return false
  }
  return true
}

async function handleExcelUpload(options: any) {
  if (!props.definition?.id) return
  try {
    const mappings: Record<string, string> = {}
    for (const field of fields.value) {
      mappings[field.label] = field.name
      mappings[`${field.label}(${field.name})`] = field.name
    }
    const formData2 = new FormData()
    formData2.append('file', options.file)
    formData2.append('definitionId', String(props.definition.id))
    formData2.append('mappings', JSON.stringify(mappings))
    const res = await request.post('/flow/import/parse', formData2, {
      headers: { 'Content-Type': 'multipart/form-data' }
    })
    const data = res as unknown as Record<string, unknown>
    formData.value = { ...formData.value, ...data }
    ElMessage.success('Excel 数据已填充')
    options.onSuccess?.()
  } catch (e: any) {
    ElMessage.error(e?.message || 'Excel 解析失败')
    options.onError?.(e)
  }
}

defineExpose({ validate, normalizeOptions })
</script>

<style scoped>
.flow-form-fields {
  padding: 4px 0;
}
.empty-tip {
  padding: 20px 0;
  text-align: center;
  font-size: 14px;
}
.form-actions {
  margin-bottom: 16px;
}
.field-list {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
}
.field-row {
  width: calc(50% - 9px);
  min-width: 240px;
  flex: 1 1 calc(50% - 9px);
}
.field-row-full {
  width: 100%;
  flex: 1 1 100%;
}
.field-label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 500;
  color: #606266;
  line-height: 1.4;
}
.required-star {
  color: #f56c6c;
  margin-left: 4px;
}
.field-control {
  width: 100%;
}
.field-control :deep(.el-input__inner),
.field-control :deep(.el-textarea__inner),
.field-control :deep(.el-input-number),
.field-control :deep(.el-date-editor),
.field-control :deep(.el-select) {
  width: 100%;
}
</style>
