<template>
  <div v-loading="loading">
    <PageHeader title="样本与模型" description="管理样本回流、数据集、模型版本、参数方案、测试评估和发布治理">
      <el-button :icon="Refresh" :loading="loading" @click="load">刷新</el-button>
    </PageHeader>

    <section class="metric-strip algorithm-metric-strip">
      <div v-for="item in metrics" :key="item.label" class="metric-card"><strong>{{ item.value }}</strong><span>{{ item.label }}</span><small>{{ item.note }}</small></div>
    </section>

    <el-tabs v-model="activeArea" class="secondary-tabs algorithm-area-tabs" @tab-change="changeArea">
      <el-tab-pane :label="`候选样本 ${sampleRows.length}`" name="samples">
        <div class="filter-bar"><el-input v-model="keyword" clearable placeholder="样本、场景、模型或任务" :prefix-icon="Search" /><el-select v-model="priorityFilter"><el-option label="全部优先级" value="" /><el-option label="高" value="high" /><el-option label="普通" value="normal" /></el-select><span class="filter-spacer"></span><span>{{ filteredSamples.length }} 个样本</span></div>
        <el-card class="workspace-card" shadow="never"><el-table :data="pagedSamples" empty-text="暂无候选样本" @row-click="previewCandidate">
          <el-table-column prop="sample_id" label="样本编号" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.sample_id }}</span><small class="cell-subtext">{{ scope.row.line_id }}</small></template></el-table-column>
          <el-table-column prop="feedback_reason" label="入池原因" min-width="130" /><el-table-column prop="target_model_group" label="目标模型" min-width="160" /><el-table-column prop="source_model_version" label="来源版本" width="100" /><el-table-column prop="priority" label="优先级" width="90" />
          <el-table-column label="状态" width="105"><template #default="scope"><el-tag :type="statusTag(scope.row.labeling_status)" effect="plain">{{ statusLabel(scope.row.labeling_status) }}</el-tag></template></el-table-column>
          <el-table-column label="质量" width="90"><template #default="scope">{{ statusLabel(scope.row.quality_status) }}</template></el-table-column>
          <el-table-column label="操作" width="200" fixed="right"><template #default="scope"><div class="list-actions" @click.stop><el-button link type="primary" @click="previewCandidate(scope.row)">预览</el-button><el-button link type="success" :disabled="scope.row.labeling_status === 'queued'" @click="decide(scope.row, 'accepted')">入池</el-button><el-button link type="danger" :disabled="scope.row.labeling_status === 'excluded'" @click="decide(scope.row, 'excluded')">排除</el-button></div></template></el-table-column>
        </el-table><el-pagination v-model:current-page="page" :page-size="50" class="table-pagination" background layout="total, prev, pager, next" :total="filteredSamples.length" /></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`标注队列 ${queuedSamples.length}`" name="labeling">
        <el-card class="workspace-card" shadow="never"><el-table :data="queuedSamples" empty-text="暂无待标注样本" @row-click="previewCandidate"><el-table-column prop="sample_id" label="样本编号" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.sample_id }}</span></template></el-table-column><el-table-column prop="target_model_group" label="模型组" /><el-table-column prop="feedback_reason" label="标注原因" /><el-table-column label="标注状态"><template #default><el-tag type="warning">待标注</el-tag></template></el-table-column><el-table-column label="操作" width="90" fixed="right"><template #default="scope"><div @click.stop><el-button link type="primary" @click="previewCandidate(scope.row)">预览</el-button></div></template></el-table-column></el-table></el-card>
      </el-tab-pane>

      <el-tab-pane label="数据集版本" name="datasets">
        <section class="dataset-grid"><div v-for="dataset in datasets" :key="dataset.name"><header><strong>{{ dataset.name }}</strong><el-tag type="success" effect="plain">有效</el-tag></header><p>{{ dataset.description }}</p><dl><div><dt>样本量</dt><dd>{{ dataset.count }}</dd></div><div><dt>目标模型</dt><dd>{{ dataset.group }}</dd></div><div><dt>版本</dt><dd>{{ dataset.version }}</dd></div></dl></div></section>
      </el-tab-pane>

      <el-tab-pane :label="`模型管理 ${modelGroupRows.length}`" name="models">
        <ModelManagementWorkspace
          v-if="activeArea === 'models'"
          :model-group-id="modelGroupId"
          :initial-task-id="initialTaskId"
        />
      </el-tab-pane>
    </el-tabs>

    <SamplePreviewDrawer v-model="previewVisible" :sample="previewSample" :loading="previewLoading" />
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { Refresh, Search } from "@element-plus/icons-vue";
import PageHeader from "../../components/common/PageHeader.vue";
import SamplePreviewDrawer from "../../components/common/SamplePreviewDrawer.vue";
import ModelManagementWorkspace from "../../components/model-management/ModelManagementWorkspace.vue";
import { decideSample, modelGroups, resourcePreview, resultEvidence, samples } from "../../services/api";
import type { JsonMap, ModelGroup, SamplePreviewData } from "../../types/model-management";
import { safeObject, statusLabel, statusTag, type Row } from "../../types/demo-run";

const route = useRoute();
const router = useRouter();
const loading = ref(false);
const sampleRows = ref<Row[]>([]);
const modelGroupRows = ref<ModelGroup[]>([]);
const activeArea = ref(route.params.entityType === "models" ? "models" : String(route.query.area || "samples"));
const keyword = ref("");
const priorityFilter = ref("");
const page = ref(1);
const previewVisible = ref(false);
const previewLoading = ref(false);
const previewSample = ref<SamplePreviewData>();

const modelGroupId = computed(() => route.params.entityType === "models" ? String(route.params.entityId || "") || undefined : undefined);
const initialTaskId = computed(() => route.query.taskId ? String(route.query.taskId) : undefined);
const filteredSamples = computed(() => sampleRows.value.filter((row) => (!priorityFilter.value || row.priority === priorityFilter.value) && (!keyword.value || `${row.sample_id} ${row.feedback_reason} ${row.target_model_group} ${row.task_id}`.toLowerCase().includes(keyword.value.toLowerCase()))));
const pagedSamples = computed(() => filteredSamples.value.slice((page.value - 1) * 50, page.value * 50));
const queuedSamples = computed(() => sampleRows.value.filter((row) => row.labeling_status === "queued"));
const metrics = computed(() => [
  { label: "候选样本", value: sampleRows.value.length, note: "巡检闭环回流" },
  { label: "待标注", value: queuedSamples.value.length, note: "已进入标注队列" },
  { label: "模型组", value: modelGroupRows.value.length, note: "稳定算法能力" },
  { label: "生产模型", value: modelGroupRows.value.filter((row) => row.production_version).length, note: "当前生效版本" },
  { label: "运行中测试", value: modelGroupRows.value.reduce((sum, row) => sum + Number(row.running_tests || 0), 0), note: "隔离测试资源池" },
  { label: "待审批发布", value: modelGroupRows.value.reduce((sum, row) => sum + Number(row.pending_releases || 0), 0), note: "模型治理待办" }
]);
const datasets = computed(() => [...new Set(sampleRows.value.map((row) => String(row.target_model_group)))].map((group, index) => ({ name: `${group}-dataset`, description: "由巡检告警、处置反馈和人工决策形成的训练数据集", count: sampleRows.value.filter((row) => row.target_model_group === group && row.labeling_status !== "excluded").length, group, version: `v1.${index + 1}.0` })));

async function load() {
  loading.value = true;
  try { [sampleRows.value, modelGroupRows.value] = await Promise.all([samples(), modelGroups()]); }
  finally { loading.value = false; }
}

function changeArea(value: string | number) {
  const area = String(value);
  if (area === "models") router.push("/algorithm-assets/models");
  else router.push({ path: "/algorithm-assets", query: { area } });
}

async function decide(row: Row, decision: "accepted" | "excluded") {
  await decideSample(String(row.sample_id), decision, String(row.priority || "normal"));
  ElMessage.success(decision === "accepted" ? "样本已进入标注队列" : "样本已排除");
  await load();
}

async function previewCandidate(row: Row) {
  previewVisible.value = true;
  previewLoading.value = true;
  previewSample.value = candidatePreview(row);
  const resourceId = String(row.resource_id || "");
  const resultId = String(row.ai_result_id || "");
  try {
    const [resourceResult, evidenceResult] = await Promise.allSettled([
      resourceId ? resourcePreview(resourceId) : Promise.resolve({}),
      resultId ? resultEvidence(resultId) : Promise.resolve({})
    ]);
    const resource = resourceResult.status === "fulfilled" ? resourceResult.value as Row : {};
    const evidence = evidenceResult.status === "fulfilled" ? evidenceResult.value as Row : {};
    previewSample.value = {
      ...candidatePreview(row),
      modality: normalizeModality(resource.resource_type),
      storage_url: String(resource.storage_url || ""),
      metadata: safeObject(resource.metadata),
      scene: String(evidence.scene || row.feedback_reason || "回流样本"),
      ground_truth: buildGroundTruth(evidence),
      evidence: safeObject(evidence) as JsonMap
    };
  } finally {
    previewLoading.value = false;
  }
}

function candidatePreview(row: Row): SamplePreviewData {
  return {
    id: String(row.sample_id),
    name: `${row.feedback_reason || "巡检回流"}样本`,
    modality: "file",
    source: "巡检闭环回流",
    scene: String(row.feedback_reason || "回流样本"),
    line_id: String(row.line_id || ""),
    label_status: String(row.labeling_status || ""),
    quality_status: String(row.quality_status || ""),
    feedback_reason: String(row.feedback_reason || ""),
    target_model_group: String(row.target_model_group || ""),
    source_model_version: String(row.source_model_version || ""),
    metadata: { task_id: row.task_id, resource_id: row.resource_id, alarm_id: row.alarm_id, workorder_id: row.workorder_id },
    ground_truth: {},
    evidence: {}
  };
}

function normalizeModality(value: unknown) {
  return value === "tif" ? "raster" : String(value || "file");
}

function buildGroundTruth(evidence: Row): JsonMap {
  const geometry = safeObject(evidence.geometry);
  if (!Object.keys(geometry).length) return {};
  return { objects: [{ category: evidence.category || evidence.scene || "证据区域", bbox: geometry }] };
}

watch([keyword, priorityFilter], () => { page.value = 1; });
watch(() => route.fullPath, () => { activeArea.value = route.params.entityType === "models" ? "models" : String(route.query.area || "samples"); });
onMounted(load);
</script>
