<script setup lang="ts">
import { computed } from 'vue'
import VChart from 'vue-echarts'
import '@/plugins/echarts'
import type { EChartsOption } from 'echarts'
import type { ResultQualityDetails } from './types'

const props = defineProps<{
  quality: ResultQualityDetails
  score?: number
}>()

// 轴标签按词意预置断行，避免长中文标签把雷达网格挤偏或被机械切词。
const JUDGE_DIMENSION_LABELS: Record<string, string> = {
  faithfulness: '忠实度',
  correctness: '正确性',
  clarity: '问题\n清晰度',
  completeness: '回答\n完整性',
  alignment: '指令\n对齐',
  reasoning_validity: '推理\n有效性',
  chosen_quality: 'chosen\n质量',
  rejected_quality: 'rejected\n质量',
  preference_reasonableness: '偏好\n区分',
}

const SEMANTIC_DIMENSION_LABELS: Record<string, string> = {
  question_answer: '问答\n相关',
  answer_source: '来源\n覆盖',
}

interface RadarDimension {
  name: string
  value: number
}

const radarDimensions = computed<RadarDimension[]>(() => {
  const dimensions: RadarDimension[] = []
  for (const [key, value] of Object.entries(props.quality?.judge?.scores ?? {})) {
    dimensions.push({
      name: JUDGE_DIMENSION_LABELS[key] ?? key,
      value: Math.round(value * 20),
    })
  }
  for (const [key, value] of Object.entries(props.quality?.semantic ?? {})) {
    if (key === 'overall' || typeof value !== 'number') continue
    dimensions.push({
      name: SEMANTIC_DIMENSION_LABELS[key] ?? key,
      value: Math.round(value),
    })
  }
  return dimensions
})

// 可用维度太少时雷达图失去意义，降级为分层分数展示。
const showRadar = computed(() => radarDimensions.value.length >= 3)

const radarOption = computed<EChartsOption>(() => ({
  radar: {
    indicator: radarDimensions.value.map((dimension) => ({
      name: dimension.name,
      max: 100,
    })),
    radius: '56%',
    center: ['50%', '50%'],
    splitNumber: 4,
    axisName: {
      color: '#667085',
      fontSize: 10,
      lineHeight: 13,
    },
    splitArea: { areaStyle: { color: ['#fbfbfd', '#f2f4f8'] } },
    splitLine: { lineStyle: { color: '#e4e7ec' } },
    axisLine: { lineStyle: { color: '#e4e7ec' } },
  },
  series: [{
    type: 'radar',
    symbol: 'circle',
    symbolSize: 3,
    data: [{
      value: radarDimensions.value.map((dimension) => dimension.value),
      name: '质量维度',
      areaStyle: { color: 'rgba(91, 80, 242, 0.18)' },
      lineStyle: { color: '#5b50f2', width: 1.5 },
      itemStyle: { color: '#5b50f2' },
    }],
  }],
}))

const layerScores = computed(() => {
  const layers = props.quality?.layers ?? {}
  return [
    { label: '规则层', value: layers.rule },
    { label: '语义层', value: layers.semantic },
    { label: '评审层', value: layers.judge },
  ].filter((layer): layer is { label: string; value: number } => (
    typeof layer.value === 'number'
  ))
})

const displayScore = computed(() => {
  if (typeof props.score === 'number' && !isNaN(props.score)) {
    return props.score.toFixed(1)
  }
  return null
})

const scoreTone = computed(() => {
  const numScore = props.score ?? 0
  return numScore >= 80 ? 'is-success' : numScore >= 60 ? 'is-warning' : 'is-danger'
})
</script>

<template>
  <div class="quality-popover">
    <div v-if="displayScore !== null" class="popover-header">
      <strong>质量评测</strong>
      <span class="popover-score" :class="scoreTone">{{ displayScore }}</span>
    </div>

    <VChart
      v-if="showRadar"
      class="quality-radar"
      :option="radarOption"
      autoresize
    />
    <div v-else class="radar-fallback">
      维度数据不足，已评测维度少于 3 个时以分层分数为准。
    </div>

    <div class="layer-scores">
      <div v-for="layer in layerScores" :key="layer.label" class="layer-item">
        <span>{{ layer.label }}</span>
        <el-progress
          :percentage="Math.round(layer.value)"
          :stroke-width="6"
          :show-text="false"
          :color="layer.value >= 80 ? '#12b76a' : layer.value >= 60 ? '#f0b429' : '#d92d20'"
        />
        <em>{{ layer.value.toFixed(0) }}</em>
      </div>
    </div>

    <p v-if="quality?.judge?.reason" class="judge-reason">{{ quality.judge.reason }}</p>
    <div v-if="quality?.judge?.issues?.length" class="judge-issues">
      <span v-for="issue in quality.judge.issues" :key="issue" class="issue-tag">{{ issue }}</span>
    </div>
    <div v-if="quality?.judge?.model" class="judge-model">评审模型：{{ quality.judge.model }}</div>
  </div>
</template>

<style scoped lang="scss">
.quality-popover {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
}

.popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 6px;
  border-bottom: 1px solid #f2f4f7;

  strong {
    color: #344054;
    font-size: 13px;
  }
}

.popover-score {
  color: #344054;
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;

  &.is-success { color: #12b76a; }
  &.is-warning { color: #d99b0b; }
  &.is-danger { color: #d92d20; }
}

.quality-radar {
  width: 100%;
  height: 220px;
  box-sizing: border-box;
}

.radar-fallback {
  padding: 18px 10px;
  color: #98a2b3;
  font-size: 12px;
  text-align: center;
}

.layer-scores {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.layer-item {
  display: grid;
  grid-template-columns: 44px 1fr 28px;
  align-items: center;
  gap: 8px;
  color: #667085;
  font-size: 11px;

  em {
    color: #344054;
    font-style: normal;
    font-weight: 600;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }
}

.judge-reason {
  margin: 0;
  color: #475467;
  font-size: 12px;
  line-height: 1.6;
}

.judge-issues {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.issue-tag {
  padding: 2px 8px;
  color: #b54708;
  background: #fef0c7;
  border-radius: 3px;
  font-size: 11px;
}

.judge-model {
  color: #98a2b3;
  font-size: 11px;
}
</style>

<style lang="scss">
.quality-radar-popper {
  padding: 14px 16px !important;
}
</style>

