<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import { MdEditor } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import PageCard from '@/components/PageCard.vue'
import {
  createDimension,
  updateDimension,
  getDimension,
} from '@/api/modules/eval'
import { getModelList } from '@/api/modules/model'
import { EVAL_METHODS, EVAL_METHOD_PROMPTS } from '@/constants/dimension'
import { DIMENSION_TYPE_MAP } from '@/constants'
import type { DimensionType, ModelItem } from '@/types'

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

const evalModels = ref<ModelItem[]>([])

const form = reactive({
  name: '',
  type: '' as DimensionType | '',
  description: '',
  eval_model: '',
  eval_method: '' as string | string[],
  eval_prompt: '',
  is_active: true,
  is_default: false,
  // text_similarity
  bleu_n: 1,
  output_precision: 3,
  // metric
  score_min: 0,
  score_max: 5,
  pass_threshold: 3,
})

const rules: FormRules = {
  name: [
    { required: true, message: '请输入维度名称', trigger: 'blur' },
    { max: 50, message: '不超过 50 字符', trigger: 'blur' },
  ],
  type: [{ required: true, message: '请选择指标类型', trigger: 'change' }],
  eval_model: [{ required: true, message: '请选择大模型', trigger: 'change' }],
  eval_prompt: [{ required: true, message: '请填写评估 Prompt', trigger: 'blur' }],
}

const typeOptions = Object.entries(DIMENSION_TYPE_MAP).map(([value, label]) => ({ value, label }))

/** 当前类型下的评估方法选项 */
const currentMethods = computed(() => (form.type ? EVAL_METHODS[form.type] || [] : []))

/** 是否文本相似度类型（多选评估方法） */
const isTextSimilarity = computed(() => form.type === 'text_similarity')

/** 切换指标类型时重置相关字段 */
watch(
  () => form.type,
  (t) => {
    if (!t) return
    const methods = EVAL_METHODS[t] || []
    const first = methods[0]?.value || ''
    form.eval_method = isTextSimilarity.value ? [first] : first
    // 切换 Prompt
    if (form.type !== 'text_similarity' && EVAL_METHOD_PROMPTS[first]) {
      form.eval_prompt = EVAL_METHOD_PROMPTS[first]
    }
  },
)

/** 评估方法变化时更新 Prompt */
watch(
  () => form.eval_method,
  (m) => {
    if (form.type === 'text_similarity' || !m) return
    const method = Array.isArray(m) ? m[0] : m
    if (method && EVAL_METHOD_PROMPTS[method]) {
      form.eval_prompt = EVAL_METHOD_PROMPTS[method]
    }
  },
)

async function loadEditData() {
  if (!editId.value) return
  try {
    const dim: any = await getDimension(editId.value)
    // 补全所有字段回填（修复原项目回填不完整 bug）
    Object.assign(form, {
      name: dim.name || '',
      type: dim.type || '',
      description: dim.description || '',
      eval_model: dim.eval_model || '',
      eval_method: dim.eval_method || (dim.type ? EVAL_METHODS[dim.type]?.[0]?.value : ''),
      eval_prompt: dim.eval_prompt || '',
      is_active: dim.is_active !== false,
      is_default: !!dim.is_default,
      bleu_n: dim.bleu_n ?? 1,
      output_precision: dim.output_precision ?? 3,
      score_min: dim.score_min ?? 0,
      score_max: dim.score_max ?? 5,
      pass_threshold: dim.pass_threshold ?? 3,
    })
  } catch {
    // ignore
  }
}

async function loadModels() {
  try {
    const all = (await getModelList()) || []
    evalModels.value = all.filter((m) => m.purpose === 'evaluation')
  } catch {
    evalModels.value = []
  }
}

async function handleSubmit() {
  if (!formRef.value) return
  await formRef.value.validate(async (valid) => {
    if (!valid) return
    submitting.value = true
    try {
      const data: any = {
        name: form.name,
        type: form.type,
        description: form.description,
        eval_model: form.type === 'text_similarity' ? null : form.eval_model,
        eval_method: form.eval_method,
        eval_prompt: form.type === 'text_similarity' ? null : form.eval_prompt,
        is_active: form.is_active,
        is_default: form.is_default,
        create_time: new Date().toISOString(),
      }
      if (form.type === 'text_similarity') {
        data.bleu_n = form.bleu_n
        data.output_precision = form.output_precision
      }
      if (form.type === 'metric') {
        data.score_min = form.score_min
        data.score_max = form.score_max
        data.pass_threshold = form.pass_threshold
      }
      if (isEdit.value && editId.value) {
        await updateDimension(editId.value, data)
        ElMessage.success('更新成功')
      } else {
        await createDimension(data)
        ElMessage.success('创建成功')
      }
      router.push('/model-eval')
    } catch {
      // ignore
    } finally {
      submitting.value = false
    }
  })
}

function handleCancel() {
  router.back()
}

onMounted(() => {
  loadModels()
  loadEditData()
})
</script>

<template>
  <PageCard :title="isEdit ? '编辑评测维度' : '添加评测维度'">
    <el-form ref="formRef" :model="form" :rules="rules" label-width="130px" style="max-width: 760px">
      <el-form-item label="维度名称" prop="name">
        <el-input v-model="form.name" placeholder="请输入维度名称" maxlength="50" show-word-limit />
      </el-form-item>

      <el-form-item label="指标类型" prop="type">
        <el-select v-model="form.type" placeholder="请选择指标类型" style="width: 100%">
          <el-option v-for="opt in typeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
        </el-select>
      </el-form-item>

      <el-form-item label="描述">
        <el-input v-model="form.description" type="textarea" :rows="2" maxlength="200" show-word-limit />
      </el-form-item>

      <!-- 分类型 / 指标型：需要选择大模型和评估方法 -->
      <template v-if="form.type === 'classification' || form.type === 'metric'">
        <el-form-item label="选择大模型" prop="eval_model">
          <el-select v-model="form.eval_model" placeholder="请选择评测模型" filterable style="width: 100%">
            <el-option v-for="m in evalModels" :key="m.id" :label="m.name" :value="m.name" />
          </el-select>
        </el-form-item>

        <el-form-item label="评估方式" prop="eval_method">
          <el-radio-group v-model="(form.eval_method as string)">
            <el-radio v-for="m in currentMethods" :key="m.value" :value="m.value">
              {{ m.name }}
              <span class="method-desc">{{ m.desc }}</span>
            </el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="评估 Prompt" prop="eval_prompt">
          <MdEditor v-model="form.eval_prompt" language="zh-CN" :toolbars-exclude="['github', 'save']" style="height: 320px" />
        </el-form-item>
      </template>

      <!-- 文本相似度：多选评估方法 + BLEU/精度配置 -->
      <template v-if="form.type === 'text_similarity'">
        <el-form-item label="评估方式">
          <el-checkbox-group v-model="(form.eval_method as string[])">
            <el-checkbox v-for="m in currentMethods" :key="m.value" :value="m.value">
              {{ m.name }}
              <span class="method-desc">{{ m.desc }}</span>
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>

        <el-form-item label="BLEU n-gram">
          <el-select v-model="form.bleu_n" style="width: 160px">
            <el-option :value="1" label="1-gram" />
            <el-option :value="2" label="2-gram" />
            <el-option :value="3" label="3-gram" />
            <el-option :value="4" label="4-gram" />
          </el-select>
        </el-form-item>

        <el-form-item label="输出精度">
          <el-select v-model="form.output_precision" style="width: 160px">
            <el-option :value="1" label="1 位小数" />
            <el-option :value="2" label="2 位小数" />
            <el-option :value="3" label="3 位小数" />
            <el-option :value="4" label="4 位小数" />
          </el-select>
        </el-form-item>
      </template>

      <!-- 指标型：评分范围 + 通过阈值 -->
      <template v-if="form.type === 'metric'">
        <el-form-item label="评分最小值">
          <el-input-number v-model="form.score_min" :min="0" :step="1" style="width: 160px" />
        </el-form-item>
        <el-form-item label="评分最大值">
          <el-input-number v-model="form.score_max" :min="0" :step="1" style="width: 160px" />
        </el-form-item>
        <el-form-item label="通过阈值">
          <div style="width: 100%">
            <el-slider
              v-model="form.pass_threshold"
              :min="form.score_min"
              :max="form.score_max"
              :step="0.5"
              show-input
              :show-input-controls="false"
            />
          </div>
        </el-form-item>
      </template>

      <el-form-item label="启用该维度">
        <el-switch v-model="form.is_active" />
      </el-form-item>
      <el-form-item label="设为默认">
        <el-switch v-model="form.is_default" />
      </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>
.method-desc {
  color: #909399;
  font-size: 12px;
  margin-left: 6px;
}
</style>
