<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, type FormInstance, type FormRules, type UploadFile } from 'element-plus'
import PageCard from '@/components/PageCard.vue'
import {
  getDataset,
  createDataset,
  updateDataset,
  uploadDatasetFiles,
} from '@/api/modules/dataset'
import type { DatasetItem } from '@/types'

const route = useRoute()
const router = useRouter()

const formRef = ref<FormInstance>()
const loading = ref(false)
const submitting = ref(false)
const isEdit = computed(() => !!route.params.id)
const editId = computed(() => route.params.id as string | undefined)

/** 允许的文件类型 */
const acceptTypes = '.json,.jsonl'

const form = reactive({
  name: '',
  description: '',
  dataset_type: 'train' as 'train' | 'eval',
  storage: 'local' as 'local' | 'cloud' | 'minio',
  // MinIO 配置
  minio_endpoint: '',
  minio_bucket: '',
  minio_access_key: '',
  minio_secret_key: '',
  minio_ssl: false,
})

const files = ref<File[]>([])
const fileCount = ref(0)
const formatValid = ref<boolean | null>(null)
const formatMessage = ref('')

const rules: FormRules = {
  name: [
    { required: true, message: '请输入数据集名称', trigger: 'blur' },
    { max: 20, message: '不超过 20 字符', trigger: 'blur' },
  ],
  description: [{ max: 50, message: '不超过 50 字符', trigger: 'blur' }],
}

/** 处理文件选择（替换模式：新文件覆盖旧文件） */
async function handleFileChange(uploadFile: UploadFile) {
  const raw = uploadFile.raw
  if (!raw) return
  const ext = raw.name.split('.').pop()?.toLowerCase()
  if (ext !== 'json' && ext !== 'jsonl') {
    ElMessage.warning('仅支持 JSON/JSONL 格式')
    return
  }
  if (raw.size > 200 * 1024 * 1024) {
    ElMessage.warning('单文件不能超过 200MB')
    return
  }
  files.value = [raw] // 替换模式
  await analyzeFile(raw)
}

/** 前端解析文件统计条数并校验 Alpaca 格式 */
async function analyzeFile(file: File) {
  try {
    const text = await file.text()
    const lines = text.trim().split('\n').filter(Boolean)
    fileCount.value = lines.length

    // Alpaca 格式校验：每行 JSON 须含 instruction 字段
    let validCount = 0
    for (const line of lines) {
      try {
        const obj = JSON.parse(line)
        if (obj.instruction !== undefined) validCount++
      } catch {
        // 非 JSON 行（如纯 JSONL 多行结构）
      }
    }
    if (validCount > 0 && validCount === lines.length) {
      formatValid.value = true
      formatMessage.value = `符合 Alpaca 格式（含 instruction 字段）`
    } else if (validCount > 0) {
      formatValid.value = true
      formatMessage.value = `部分符合 Alpaca 格式（${validCount}/${lines.length}）`
    } else {
      formatValid.value = false
      formatMessage.value = '未检测到标准 Alpaca 格式（缺少 instruction 字段），仍可上传'
    }
  } catch {
    fileCount.value = 0
    formatValid.value = null
    formatMessage.value = '文件解析失败'
  }
}

/** 自定义上传（阻止自动上传，仅收集文件） */
function customUpload() {
  return Promise.resolve()
}

function handleRemove() {
  files.value = []
  fileCount.value = 0
  formatValid.value = null
  formatMessage.value = ''
}

async function loadEditData() {
  if (!editId.value) return
  loading.value = true
  try {
    const ds: any = await getDataset(editId.value)
    Object.assign(form, {
      name: ds.name || '',
      description: ds.description || '',
      dataset_type: ds.type === 'eval' ? 'eval' : 'train',
      storage: ds.storage_type || 'local',
    })
    fileCount.value = ds.count || 0
  } catch {
    // ignore
  } finally {
    loading.value = false
  }
}

async function handleSubmit() {
  if (!formRef.value) return
  await formRef.value.validate(async (valid) => {
    if (!valid) return
    if (!isEdit.value && files.value.length === 0) {
      ElMessage.warning('请至少上传一个数据集文件')
      return
    }
    submitting.value = true
    try {
      const baseData: Partial<DatasetItem> = {
        name: form.name,
        type: form.dataset_type,
        storage_type: form.storage,
        description: form.description,
        count: fileCount.value,
      }
      // MinIO 配置
      if (form.storage === 'minio') {
        ;(baseData as any).minio_config = {
          endpoint: form.minio_endpoint,
          bucket: form.minio_bucket,
          access_key: form.minio_access_key,
          secret_key: form.minio_secret_key,
          ssl: form.minio_ssl,
        }
      }

      if (isEdit.value && editId.value) {
        // 编辑：更新记录 + 可选上传新文件
        await updateDataset(editId.value, baseData)
        if (files.value.length > 0) {
          await uploadDatasetFiles(editId.value, files.value)
        }
        ElMessage.success('更新成功')
      } else {
        // 新建：创建记录 → 上传文件 → 更新 count
        const res: any = await createDataset(baseData)
        const newId = res?.id || res
        if (files.value.length > 0) {
          await uploadDatasetFiles(newId, files.value)
          await updateDataset(newId, { count: fileCount.value })
        }
        ElMessage.success('上传成功')
      }
      router.push('/dataset')
    } catch {
      // ignore
    } finally {
      submitting.value = false
    }
  })
}

function handleCancel() {
  router.back()
}

onMounted(loadEditData)
</script>

<template>
  <PageCard :title="isEdit ? '编辑数据集' : '上传数据集'" v-loading="loading">
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="120px"
      style="max-width: 640px"
    >
      <el-form-item label="数据集名称" prop="name">
        <el-input v-model="form.name" placeholder="请输入数据集名称" maxlength="20" show-word-limit />
      </el-form-item>

      <el-form-item label="数据集描述">
        <el-input
          v-model="form.description"
          type="textarea"
          :rows="2"
          maxlength="50"
          show-word-limit
          placeholder="选填"
        />
      </el-form-item>

      <el-form-item label="数据集类型">
        <el-radio-group v-model="form.dataset_type">
          <el-radio value="train">训练集</el-radio>
          <el-radio value="eval">评测集</el-radio>
        </el-radio-group>
      </el-form-item>

      <el-form-item label="上传方式">
        <el-radio-group v-model="form.storage">
          <el-radio value="local">本地</el-radio>
          <el-radio value="cloud">云平台</el-radio>
          <el-radio value="minio">MinIO</el-radio>
        </el-radio-group>
      </el-form-item>

      <!-- MinIO 配置 -->
      <template v-if="form.storage === 'minio'">
        <el-form-item label="Endpoint">
          <el-input v-model="form.minio_endpoint" placeholder="如：http://minio:9000" />
        </el-form-item>
        <el-form-item label="Bucket">
          <el-input v-model="form.minio_bucket" placeholder="请输入 Bucket 名称" />
        </el-form-item>
        <el-form-item label="Access Key">
          <el-input v-model="form.minio_access_key" placeholder="请输入 Access Key" />
        </el-form-item>
        <el-form-item label="Secret Key">
          <el-input v-model="form.minio_secret_key" type="password" show-password placeholder="请输入 Secret Key" />
        </el-form-item>
        <el-form-item label="启用 SSL">
          <el-switch v-model="form.minio_ssl" />
        </el-form-item>
      </template>

      <!-- 文件上传（仅本地存储） -->
      <el-form-item v-if="form.storage === 'local'" label="上传文件">
        <div style="width: 100%">
          <el-upload
            drag
            :accept="acceptTypes"
            :auto-upload="false"
            :show-file-list="false"
            :http-request="customUpload"
            :on-change="handleFileChange"
          >
            <i class="fa fa-cloud-upload" style="font-size: 32px; color: #1890ff" />
            <div class="el-upload__text">
              将文件拖到此处，或<em>点击上传</em>
            </div>
            <template #tip>
              <div class="el-upload__tip">仅支持 JSON/JSONL 格式，单文件不超过 200MB</div>
            </template>
          </el-upload>

          <!-- 已选文件列表 -->
          <div v-for="f in files" :key="f.name" class="file-item">
            <div class="file-info">
              <i class="fa fa-file-code-o" />
              <span class="file-name">{{ f.name }}</span>
              <span class="file-size">{{ (f.size / 1024).toFixed(1) }} KB</span>
            </div>
            <el-button link type="danger" size="small" @click="handleRemove">
              <i class="fa fa-times" />
            </el-button>
          </div>

          <!-- 格式校验提示 -->
          <el-alert
            v-if="formatMessage"
            :title="formatMessage"
            :type="formatValid ? 'success' : 'warning'"
            :closable="false"
            show-icon
            style="margin-top: 8px"
          />
          <div v-if="fileCount" class="record-count">解析到 {{ fileCount }} 条记录</div>
        </div>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" :loading="submitting" @click="handleSubmit">
          {{ isEdit ? '保存' : '上传' }}
        </el-button>
        <el-button @click="handleCancel">取消</el-button>
      </el-form-item>
    </el-form>
  </PageCard>
</template>

<style scoped>
.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  margin-top: 8px;
}
.file-info {
  display: flex;
  align-items: center;
  gap: 8px;
}
.file-name {
  color: #303133;
}
.file-size {
  color: #909399;
  font-size: 12px;
}
.record-count {
  margin-top: 8px;
  font-size: 13px;
  color: #909399;
}
</style>
