<script setup lang="ts">
import { ref, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import type { DatasetItem, GpuInfo, TrainedModel } from '@/types'

export interface EvalTaskSetupDraft {
  eval_task_name: string
  model_id: string | number
  gpu_id: string | number
  data_source: 'dataset' | 'inference'
  dataset_id: string | number
  leaderboard: boolean
}

defineProps<{
  trainedModels: TrainedModel[]
  evalDatasets: DatasetItem[]
  gpus: GpuInfo[]
  loading?: boolean
  disabled?: boolean
}>()

const form = defineModel<EvalTaskSetupDraft>({ required: true })
const formRef = ref<FormInstance>()

const rules: FormRules<EvalTaskSetupDraft> = {
  eval_task_name: [
    { required: true, message: '请输入任务名称', trigger: 'blur' },
    { max: 50, message: '任务名称不超过 50 个字符', trigger: 'blur' },
  ],
  model_id: [{ required: true, message: '请选择评测模型', trigger: 'change' }],
  gpu_id: [{ required: true, message: '请选择 GPU', trigger: 'change' }],
  dataset_id: [
    {
      validator: (_rule, value, callback) => {
        if (form.value.data_source === 'dataset' && (value === '' || value === null || value === undefined)) {
          callback(new Error('请选择评测数据集'))
          return
        }
        callback()
      },
      trigger: 'change',
    },
  ],
}

watch(
  () => form.value.data_source,
  (source) => {
    if (source !== 'dataset') {
      form.value.dataset_id = ''
      formRef.value?.clearValidate('dataset_id')
    }
  },
)

async function validate() {
  if (!formRef.value) return false
  try {
    const valid = await formRef.value.validate()
    return !!valid
  } catch {
    return false
  }
}

defineExpose({ validate })
</script>

<template>
  <el-form
    ref="formRef"
    :model="form"
    :rules="rules"
    label-width="120px"
    class="step-form"
    :disabled="disabled"
    scroll-to-error
  >
    <el-form-item label="任务名称" prop="eval_task_name">
      <el-input v-model="form.eval_task_name" placeholder="请输入任务名称" maxlength="50" show-word-limit />
    </el-form-item>

    <el-form-item label="评测模型" prop="model_id">
      <el-select
        v-model="form.model_id"
        placeholder="请选择已训练且已合并的模型"
        filterable
        style="width: 100%"
        :loading="loading"
      >
        <el-option
          v-for="model in trainedModels"
          :key="model.id"
          :label="model.name"
          :value="model.id"
          :disabled="!model.merged"
        />
      </el-select>
      <div class="field-tip">未完成合并的模型不可用于评测。</div>
    </el-form-item>

    <el-form-item label="选择 GPU" prop="gpu_id">
      <el-select v-model="form.gpu_id" placeholder="请选择 GPU" style="width: 100%" :loading="loading">
        <el-option
          v-for="(gpu, index) in gpus"
          :key="index"
          :label="`${gpu.name} (GPU ${index})`"
          :value="index"
        />
      </el-select>
    </el-form-item>

    <el-form-item label="数据来源">
      <el-radio-group v-model="form.data_source">
        <el-radio value="dataset">评测数据集</el-radio>
        <el-radio value="inference">推理结果集</el-radio>
      </el-radio-group>
    </el-form-item>

    <el-form-item v-if="form.data_source === 'dataset'" label="评测数据集" prop="dataset_id">
      <el-select
        v-model="form.dataset_id"
        placeholder="请选择评测数据集"
        filterable
        style="width: 100%"
        :loading="loading"
      >
        <el-option v-for="dataset in evalDatasets" :key="dataset.id" :label="dataset.name" :value="dataset.id" />
      </el-select>
    </el-form-item>

    <el-alert
      v-else
      title="将使用该模型最近一次可用的推理结果集。"
      type="info"
      :closable="false"
      show-icon
      class="source-alert"
    />

    <el-form-item label="加入排行榜">
      <el-switch v-model="form.leaderboard" />
    </el-form-item>
  </el-form>
</template>

<style scoped>
.step-form {
  max-width: 760px;
}

.field-tip {
  color: #909399;
  font-size: 12px;
  line-height: 20px;
}

.source-alert {
  margin: -4px 0 20px 120px;
  max-width: 640px;
}
</style>
