<template>
  <div v-loading="loading">
    <PageHeader title="智能分析" description="管理分析任务、模型推理结果、规则判定和异常降级">
      <el-button :icon="Refresh" :loading="loading" @click="load">刷新</el-button>
    </PageHeader>

    <section class="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="activeTab" class="secondary-tabs">
      <el-tab-pane :label="`分析任务 ${jobRows.length}`" name="jobs">
        <div class="filter-bar"><el-input v-model="keyword" clearable placeholder="分析任务或巡检任务" :prefix-icon="Search" /><el-select v-model="statusFilter"><el-option label="全部状态" value="" /><el-option label="排队中" value="queued" /><el-option label="执行中" value="running" /><el-option label="已完成" value="completed" /><el-option label="失败" value="failed" /></el-select><span class="filter-spacer"></span><span>{{ filteredJobs.length }} 个分析任务</span></div>
        <el-card class="workspace-card" shadow="never"><el-table :data="pagedJobs" empty-text="暂无分析任务"><el-table-column prop="analysis_job_id" label="分析任务" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.analysis_job_id }}</span></template></el-table-column><el-table-column prop="task_id" label="巡检任务" min-width="170" show-overflow-tooltip /><el-table-column prop="line_id" label="线路" width="105" /><el-table-column label="资源" width="85"><template #default="scope">{{ arrayCount(scope.row.resource_ids) }}</template></el-table-column><el-table-column label="场景" width="85"><template #default="scope">{{ arrayCount(scope.row.scene_set) }}</template></el-table-column><el-table-column prop="analysis_mode" label="模式" width="90" /><el-table-column label="状态" width="105"><template #default="scope"><el-tag :type="statusTag(scope.row.status)" effect="plain">{{ statusLabel(scope.row.status) }}</el-tag></template></el-table-column><el-table-column label="操作" width="100"><template #default="scope"><el-button link type="primary" :disabled="scope.row.status === 'running'" @click="rerun(scope.row)">重新执行</el-button></template></el-table-column></el-table><el-pagination v-model:current-page="jobPage" :page-size="50" class="table-pagination" background layout="total, prev, pager, next" :total="filteredJobs.length" /></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`AI 结果 ${resultRows.length}`" name="results">
        <div class="filter-bar"><el-input v-model="keyword" clearable placeholder="场景、类别、模型或资源" :prefix-icon="Search" /><el-select v-model="sceneFilter"><el-option label="全部场景" value="" /><el-option v-for="scene in scenes" :key="scene" :label="scene" :value="scene" /></el-select><span class="filter-spacer"></span><span>{{ filteredResults.length }} 项结果</span></div>
        <el-card class="workspace-card" shadow="never"><el-table :data="pagedResults" empty-text="暂无 AI 结果" @row-click="inspectResult"><el-table-column prop="ai_result_id" label="结果编号" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.ai_result_id }}</span></template></el-table-column><el-table-column prop="scene" label="场景" min-width="135" /><el-table-column prop="category" label="类别" min-width="120" /><el-table-column label="置信度" width="100"><template #default="scope"><strong>{{ Number(scope.row.confidence || 0).toFixed(2) }}</strong></template></el-table-column><el-table-column prop="model_name" label="模型" min-width="145" /><el-table-column prop="model_version" label="版本" width="95" /><el-table-column prop="resource_type" label="资源" width="90" /><el-table-column label="操作" width="120"><template #default="scope"><div class="list-actions" @click.stop><el-button link type="primary" @click="inspectResult(scope.row)">证据</el-button><el-button link type="primary" @click="router.push({ path: '/gis', query: { resultId: scope.row.ai_result_id } })">定位</el-button></div></template></el-table-column></el-table><el-pagination v-model:current-page="resultPage" :page-size="50" class="table-pagination" background layout="total, prev, pager, next" :total="filteredResults.length" /></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`规则判定 ${ruleRows.length}`" name="rules">
        <el-card class="workspace-card" shadow="never"><el-table :data="pagedRules" empty-text="暂无规则判定"><el-table-column prop="alarm_id" label="关联告警" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.alarm_id }}</span></template></el-table-column><el-table-column prop="scene" label="场景" min-width="140" /><el-table-column label="规则依据" min-width="220"><template #default="scope">{{ ruleText(scope.row.rule_hits) }}</template></el-table-column><el-table-column label="空间位置" min-width="160"><template #default="scope">{{ locationText(scope.row.location) }}</template></el-table-column><el-table-column label="结论" width="100"><template #default="scope"><el-tag :type="scope.row.suppressed ? 'info' : 'danger'">{{ scope.row.suppressed ? '已抑制' : '命中' }}</el-tag></template></el-table-column><el-table-column label="操作" width="90"><template #default="scope"><el-button link type="primary" @click="router.push(`/alarms/${scope.row.alarm_id}`)">告警</el-button></template></el-table-column></el-table><el-pagination v-model:current-page="rulePage" :page-size="50" class="table-pagination" background layout="total, prev, pager, next" :total="ruleRows.length" /></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`失败与降级 ${failedJobs.length}`" name="failed">
        <el-empty v-if="failedJobs.length === 0" description="当前没有失败或降级的分析任务" />
        <el-card v-else class="workspace-card" shadow="never"><el-table :data="failedJobs"><el-table-column prop="analysis_job_id" label="分析任务" /><el-table-column prop="task_id" label="巡检任务" /><el-table-column prop="status" label="状态" /><el-table-column label="操作"><template #default="scope"><el-button link type="primary" @click="rerun(scope.row)">重新执行</el-button></template></el-table-column></el-table></el-card>
      </el-tab-pane>
    </el-tabs>

    <el-drawer v-model="detailVisible" title="AI 结果证据" size="580px"><el-skeleton v-if="detailLoading" :rows="8" animated /><template v-else><div class="evidence-canvas"><span>{{ detail.scene }}</span><strong>{{ detail.category }}</strong><em>{{ Number(detail.confidence || 0).toFixed(2) }}</em></div><el-descriptions :column="1" border><el-descriptions-item label="结果编号"><span class="entity-id">{{ detail.ai_result_id }}</span></el-descriptions-item><el-descriptions-item label="模型">{{ detail.model_name }} / {{ detail.model_version }}</el-descriptions-item><el-descriptions-item label="资源">{{ detail.resource_id }} / {{ detail.resource_type }}</el-descriptions-item><el-descriptions-item label="存储地址">{{ detail.storage_url }}</el-descriptions-item></el-descriptions><pre class="detail-json">{{ evidenceJson }}</pre></template></el-drawer>
  </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 { alarms, analysisJobs, analysisResults, resultEvidence, runAnalysisJob } from "../../services/api";
import { safeObject, statusLabel, statusTag, type Row } from "../../types/demo-run";

const route = useRoute(); const router = useRouter(); const loading = ref(false); const jobRows = ref<Row[]>([]); const resultRows = ref<Row[]>([]); const ruleRows = ref<Row[]>([]);
const activeTab = ref(String(route.query.tab || (route.params.entityType === "results" ? "results" : "jobs"))); const keyword = ref(""); const statusFilter = ref(""); const sceneFilter = ref(""); const detailVisible = ref(false); const detailLoading = ref(false); const detail = ref<Row>({});
const jobPage = ref(1); const resultPage = ref(1); const rulePage = ref(1);
const scenes = computed(() => [...new Set(resultRows.value.map((row) => String(row.scene)).filter(Boolean))]);
const failedJobs = computed(() => jobRows.value.filter((row) => ["failed", "degraded"].includes(String(row.status))));
const filteredJobs = computed(() => jobRows.value.filter((row) => (!statusFilter.value || row.status === statusFilter.value) && (!keyword.value || `${row.analysis_job_id} ${row.task_id}`.toLowerCase().includes(keyword.value.toLowerCase()))));
const filteredResults = computed(() => resultRows.value.filter((row) => (!sceneFilter.value || row.scene === sceneFilter.value) && (!route.query.resourceId || row.resource_id === route.query.resourceId) && (!keyword.value || `${row.scene} ${row.category} ${row.model_name} ${row.resource_id}`.toLowerCase().includes(keyword.value.toLowerCase()))));
const pagedJobs = computed(() => filteredJobs.value.slice((jobPage.value - 1) * 50, jobPage.value * 50));
const pagedResults = computed(() => filteredResults.value.slice((resultPage.value - 1) * 50, resultPage.value * 50));
const pagedRules = computed(() => ruleRows.value.slice((rulePage.value - 1) * 50, rulePage.value * 50));
const metrics = computed(() => [{ label: "分析任务", value: jobRows.value.length, note: "全部处理批次" }, { label: "AI 结果", value: resultRows.value.length, note: "检测与分析结果" }, { label: "规则命中", value: ruleRows.value.filter((row) => !row.suppressed).length, note: "形成有效告警" }, { label: "涉及模型", value: new Set(resultRows.value.map((row) => row.model_name)).size, note: "当前模型组" }, { label: "失败与降级", value: failedJobs.value.length, note: "需要恢复" }]);
const evidenceJson = computed(() => JSON.stringify({ geometry: safeObject(detail.value.geometry), measurements: safeObject(detail.value.measurements), attributes: safeObject(detail.value.attributes) }, null, 2));
function parseArray(value: unknown): unknown[] { try { return Array.isArray(value) ? value : JSON.parse(String(value || "[]")); } catch { return []; } }
function arrayCount(value: unknown) { return parseArray(value).length; }
function ruleText(value: unknown) { return parseArray(value).join(" / ") || "业务规则命中"; }
function locationText(value: unknown) { const location = safeObject(value); return [location.mileage, location.distance_to_track_m ? `${location.distance_to_track_m}m` : ""].filter(Boolean).join(" / ") || "线路邻近"; }
async function load() { loading.value = true; try { [jobRows.value, resultRows.value, ruleRows.value] = await Promise.all([analysisJobs(), analysisResults(), alarms(true)]); const id = String(route.params.entityId || ""); if (route.params.entityType === "results" && id) { const row = resultRows.value.find((item) => String(item.ai_result_id) === id); if (row) inspectResult(row); } } finally { loading.value = false; } }
async function rerun(row: Row) { await runAnalysisJob(String(row.analysis_job_id)); ElMessage.success("分析任务已重新执行"); await load(); }
async function inspectResult(row: Row) { detailVisible.value = true; detailLoading.value = true; router.replace({ path: `/analysis/results/${row.ai_result_id}`, query: { ...route.query, tab: "results" } }); try { detail.value = await resultEvidence(String(row.ai_result_id)); } finally { detailLoading.value = false; } }
watch(detailVisible, (visible) => { if (!visible && route.params.entityId) router.replace({ path: "/analysis", query: { ...route.query, tab: "results" } }); });
watch([keyword, statusFilter, sceneFilter], () => { jobPage.value = 1; resultPage.value = 1; });
onMounted(load);
</script>
