<template>
  <div v-loading="loading" class="evaluation-workspace">
    <div class="model-toolbar">
      <el-select v-model="statusFilter" clearable placeholder="全部状态" @change="load">
        <el-option label="已完成" value="completed" /><el-option label="部分完成" value="partially_completed" /><el-option label="运行中" value="running" /><el-option label="失败" value="failed" />
      </el-select>
      <el-input v-model="keyword" clearable placeholder="任务名称或编号" :prefix-icon="Search" />
      <span class="filter-spacer"></span>
      <el-button :icon="Refresh" @click="load">刷新</el-button>
      <el-button type="primary" :icon="DataAnalysis" :disabled="selection.length < 1" @click="compareSelection">比较所选</el-button>
    </div>

    <section class="evaluation-metrics">
      <div><strong>{{ completedCount }}</strong><span>已完成任务</span><small>当前模型组</small></div>
      <div><strong>{{ passedCount }}</strong><span>评估通过</span><small>满足发布门槛</small></div>
      <div><strong>{{ runningCount }}</strong><span>运行中</span><small>异步测试队列</small></div>
      <div><strong>{{ failedInputCount }}</strong><span>失败输入</span><small>需要检查或回流</small></div>
    </section>

    <div v-if="comparisonSeries.length" class="evaluation-chart-panel">
      <header><div><strong>指标横向比较</strong><span>{{ comparisonSeries.length }} 个模型与参数组合</span></div><el-button text :icon="Close" @click="comparisonSeries = []">关闭</el-button></header>
      <MetricComparisonChart :series="comparisonSeries" />
    </div>

    <el-card class="workspace-card" shadow="never">
      <el-table :data="filteredTests" row-key="id" @selection-change="selection = $event">
        <el-table-column type="selection" width="46" />
        <el-table-column label="测试任务" min-width="250">
          <template #default="scope"><button class="entity-link" @click="openDetail(scope.row)"><strong>{{ scope.row.name }}</strong><small>{{ scope.row.task_no }} · {{ scope.row.test_type }}</small></button></template>
        </el-table-column>
        <el-table-column label="状态" width="110"><template #default="scope"><el-tag :type="statusTagType(scope.row.status)" effect="plain">{{ testStatusLabel(scope.row.status) }}</el-tag></template></el-table-column>
        <el-table-column prop="executed_versions" label="执行版本" min-width="140" />
        <el-table-column label="规模" width="120"><template #default="scope">{{ scope.row.input_count }} × {{ scope.row.matrix_count }}<small class="cell-subtext">输入 × 组合</small></template></el-table-column>
        <el-table-column label="结果" width="125"><template #default="scope"><span class="success-count">{{ scope.row.success_count }}</span> / <span :class="{ 'failure-count': Number(scope.row.failure_count) > 0 }">{{ scope.row.failure_count }}</span><small class="cell-subtext">成功 / 失败</small></template></el-table-column>
        <el-table-column label="进度" min-width="150"><template #default="scope"><el-progress :percentage="Number(scope.row.progress)" :status="scope.row.status === 'failed' ? 'exception' : scope.row.status === 'completed' ? 'success' : undefined" /></template></el-table-column>
        <el-table-column label="创建时间" width="170"><template #default="scope">{{ formatDateTime(scope.row.created_at) }}</template></el-table-column>
        <el-table-column label="操作" width="205" fixed="right"><template #default="scope"><el-button link type="primary" @click="openDetail(scope.row)">查看</el-button><el-button link :icon="Download" @click="downloadReport(scope.row)">报告</el-button><el-button link @click="clone(scope.row)">复制</el-button></template></el-table-column>
      </el-table>
    </el-card>

    <el-drawer v-model="detailOpen" size="min(980px, 94vw)" :title="detailTask?.name || '测试详情'">
      <template v-if="detailTask">
        <div class="evaluation-detail-head"><el-tag :type="statusTagType(detailTask.status)" effect="dark">{{ testStatusLabel(detailTask.status) }}</el-tag><span><strong>{{ detailTask.task_no }}</strong><small>{{ detailTask.trace_id }} · {{ formatDateTime(detailTask.created_at) }}</small></span></div>
        <el-tabs v-model="detailTab">
          <el-tab-pane label="评估结论" name="summary">
            <div class="summary-detail-list">
              <section v-for="summary in detailSummaries" :key="summary.id">
                <header><div><strong>{{ summary.model_version }} · {{ summary.parameter_profile_name || "临时参数" }}</strong><span>{{ summary.conclusion }}</span></div><el-tag :type="summary.acceptance_status === 'passed' ? 'success' : 'danger'" effect="dark">{{ summary.acceptance_status === "passed" ? "通过" : "未通过" }}</el-tag></header>
                <dl><div v-for="([key, value]) in Object.entries(summary.metrics)" :key="key"><dt>{{ metricLabel(key) }}</dt><dd>{{ metricValue(key, value) }}</dd><small v-if="summary.baseline_delta[key] !== undefined" :class="Number(summary.baseline_delta[key]) >= 0 ? 'positive' : 'negative'">较基线 {{ signedValue(summary.baseline_delta[key]) }}</small></div></dl>
                <el-table :data="summary.acceptance_details" size="small"><el-table-column prop="metric" label="验收指标"><template #default="scope">{{ metricLabel(scope.row.metric) }}</template></el-table-column><el-table-column prop="actual" label="实际值" /><el-table-column label="门槛"><template #default="scope">{{ scope.row.operator }} {{ scope.row.expected }}</template></el-table-column><el-table-column label="结论"><template #default="scope"><el-tag :type="scope.row.passed ? 'success' : 'danger'" size="small">{{ scope.row.passed ? "通过" : "未通过" }}</el-tag></template></el-table-column></el-table>
              </section>
            </div>
          </el-tab-pane>
          <el-tab-pane :label="`结果明细 ${detailResults.length}`" name="results">
            <el-table :data="detailResults" max-height="600"><el-table-column prop="input_name" label="输入" min-width="200" /><el-table-column prop="model_version" label="版本" width="90" /><el-table-column label="状态" width="90"><template #default="scope"><el-tag :type="statusTagType(scope.row.status)" size="small">{{ scope.row.status }}</el-tag></template></el-table-column><el-table-column label="平均置信度"><template #default="scope">{{ metricValue('average_confidence', scope.row.metrics.average_confidence) }}</template></el-table-column><el-table-column label="总耗时"><template #default="scope">{{ scope.row.timings.total_ms || 0 }} ms</template></el-table-column></el-table>
          </el-tab-pane>
          <el-tab-pane :label="`运行事件 ${detailTask.events.length}`" name="events">
            <el-timeline><el-timeline-item v-for="event in [...detailTask.events].reverse()" :key="event.event_id" :timestamp="formatDateTime(event.created_at)" placement="top" :type="event.status === 'failed' ? 'danger' : event.status === 'completed' ? 'success' : 'primary'"><strong>{{ event.message }}</strong><p>{{ event.step_key }} · {{ event.event_type }} · {{ event.progress }}%</p></el-timeline-item></el-timeline>
          </el-tab-pane>
        </el-tabs>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { ElMessage } from "element-plus";
import { Close, DataAnalysis, Download, Refresh, Search } from "@element-plus/icons-vue";
import MetricComparisonChart from "./MetricComparisonChart.vue";
import { cloneModelTest, compareModelTests, modelTestDetail, modelTestReport, modelTestResults, modelTestSummaries, modelTests } from "../../services/api";
import { formatDateTime, type JsonMap, type ModelGroup, type ModelTestTask, statusTagType, testStatusLabel, type TestResult, type TestSummary } from "../../types/model-management";

const props = defineProps<{ group: ModelGroup }>();
const loading = ref(false);
const tests = ref<JsonMap[]>([]);
const selection = ref<JsonMap[]>([]);
const statusFilter = ref("");
const keyword = ref("");
const comparisonSeries = ref<Array<{ name: string; metrics: JsonMap }>>([]);
const detailOpen = ref(false);
const detailTab = ref("summary");
const detailTask = ref<ModelTestTask>();
const detailResults = ref<TestResult[]>([]);
const detailSummaries = ref<TestSummary[]>([]);

const filteredTests = computed(() => tests.value.filter((item) => !keyword.value || `${item.name} ${item.task_no}`.toLowerCase().includes(keyword.value.toLowerCase())));
const completedCount = computed(() => tests.value.filter((item) => ["completed", "partially_completed"].includes(String(item.status))).length);
const passedCount = computed(() => tests.value.filter((item) => item.status === "completed").length);
const runningCount = computed(() => tests.value.filter((item) => ["queued", "running", "validating"].includes(String(item.status))).length);
const failedInputCount = computed(() => tests.value.reduce((sum, item) => sum + Number(item.failure_count || 0), 0));

async function load() {
  loading.value = true;
  try { tests.value = await modelTests({ modelGroupId: props.group.id, status: statusFilter.value || undefined, limit: 200 }); }
  finally { loading.value = false; }
}

async function compareSelection() {
  const data = await compareModelTests(selection.value.map((item) => String(item.id)));
  comparisonSeries.value = data.series.map((item: any) => ({
    name: `${item.task_name} · ${item.model_version}`,
    metrics: item.metrics
  }));
}

async function openDetail(row: JsonMap) {
  detailOpen.value = true;
  detailTab.value = "summary";
  [detailTask.value, detailResults.value, detailSummaries.value] = await Promise.all([
    modelTestDetail(String(row.id)), modelTestResults(String(row.id)), modelTestSummaries(String(row.id))
  ]);
}

async function clone(row: JsonMap) {
  const result = await cloneModelTest(String(row.id));
  ElMessage.success(`已复制为任务 ${result.task_no}`);
  await load();
}

async function downloadReport(row: JsonMap) {
  const blob = await modelTestReport(String(row.id));
  const url = URL.createObjectURL(blob);
  const anchor = document.createElement("a");
  anchor.href = url;
  anchor.download = `${String(row.task_no || row.id)}-report.md`;
  anchor.click();
  URL.revokeObjectURL(url);
}

function metricLabel(value: string) { return ({ precision: "精确率", recall: "召回率", f1: "F1", map50: "mAP50", miou: "mIoU", dice: "Dice", boundary_f1: "边界 F1", temperature_error_c: "温度误差", hotspot_recall: "热点召回", registration_error_m: "配准误差", anomaly_recall: "异常召回", iou: "IoU", p95_latency_ms: "P95 耗时", failure_rate: "失败率", sample_count: "样本量", average_confidence: "平均置信度", result_count: "结果数量" } as Record<string, string>)[value] || value; }
function metricValue(key: string, value: unknown) { const number = Number(value); if (Number.isNaN(number)) return String(value ?? "-"); if (["precision", "recall", "f1", "map50", "miou", "dice", "boundary_f1", "hotspot_recall", "anomaly_recall", "iou", "failure_rate", "average_confidence"].includes(key)) return `${(number * 100).toFixed(1)}%`; if (key.includes("latency")) return `${number.toFixed(0)} ms`; if (key.includes("error_m")) return `${number.toFixed(3)} m`; if (key.includes("temperature")) return `${number.toFixed(2)}°C`; return Number.isInteger(number) ? String(number) : number.toFixed(3); }
function signedValue(value: unknown) { const number = Number(value); return `${number >= 0 ? "+" : ""}${number.toFixed(4)}`; }

onMounted(load);
</script>
