<template>
  <div v-loading="loading">
    <PageHeader title="数据资源" description="管理多源数据接入、预处理、质量检查和资源预览">
      <el-button :icon="Refresh" :loading="loading" @click="load">刷新</el-button>
      <el-button type="primary" :icon="Upload" @click="uploadVisible = true">上传巡检资源</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="资源库" name="library">
        <div class="filter-bar"><el-input v-model="keyword" clearable placeholder="资源编号、任务或存储路径" :prefix-icon="Search" /><el-select v-model="typeFilter"><el-option label="全部类型" value="" /><el-option v-for="item in resourceTypes" :key="item.value" :label="item.label" :value="item.value" /></el-select><span class="filter-spacer"></span><span>{{ filteredRows.length }} 项资源</span></div>
        <el-card class="workspace-card" shadow="never"><el-table :data="filteredRows" empty-text="暂无数据资源" @row-click="inspect">
          <el-table-column prop="resource_id" label="资源编号" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.resource_id }}</span><small class="cell-subtext">{{ fileName(scope.row.storage_url) }}</small></template></el-table-column>
          <el-table-column label="类型" width="105"><template #default="scope">{{ typeLabel(scope.row.resource_type) }}</template></el-table-column>
          <el-table-column prop="task_id" label="来源任务" min-width="165" show-overflow-tooltip />
          <el-table-column prop="line_id" label="线路" width="110" />
          <el-table-column label="元数据" min-width="170"><template #default="scope">{{ metadataSummary(scope.row.metadata) }}</template></el-table-column>
          <el-table-column label="分析状态" width="105"><template #default="scope"><el-tag :type="statusTag(scope.row.analysis_status)" effect="plain">{{ statusLabel(scope.row.analysis_status) }}</el-tag></template></el-table-column>
          <el-table-column label="接入时间" min-width="165"><template #default="scope">{{ formatDateTime(scope.row.created_at) }}</template></el-table-column>
          <el-table-column label="操作" width="130" fixed="right"><template #default="scope"><div class="list-actions" @click.stop><el-button link type="primary" @click="inspect(scope.row)">预览</el-button><el-button link type="primary" @click="router.push({ path: '/analysis', query: { resourceId: scope.row.resource_id, tab: 'results' } })">结果</el-button></div></template></el-table-column>
        </el-table></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`接入监控 ${rows.length}`" name="ingest">
        <el-card class="workspace-card" shadow="never"><el-table :data="rows.slice(0, 100)" empty-text="暂无接入记录">
          <el-table-column prop="resource_id" label="资源" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.resource_id }}</span></template></el-table-column><el-table-column label="上传" min-width="170"><template #default><el-progress :percentage="100" :stroke-width="7" status="success" /></template></el-table-column><el-table-column label="完整性" width="110"><template #default><el-tag type="success" effect="plain">校验通过</el-tag></template></el-table-column><el-table-column label="时间同步" width="110"><template #default><el-tag type="success" effect="plain">已同步</el-tag></template></el-table-column><el-table-column label="入库" width="100"><template #default><el-tag type="success">已入库</el-tag></template></el-table-column>
        </el-table></el-card>
      </el-tab-pane>

      <el-tab-pane :label="`预处理记录 ${preprocessRows.length}`" name="preprocess">
        <div class="processor-summary">
          <div v-for="processor in processors" :key="processor.type"><span>{{ processor.type }}</span><strong>{{ typeCount(processor.key) }}</strong><small>{{ processor.steps }}</small></div>
        </div>
        <el-card class="workspace-card" shadow="never"><el-table :data="preprocessRows" empty-text="暂无预处理记录">
          <el-table-column prop="resource_id" label="资源" min-width="170"><template #default="scope"><span class="entity-id">{{ scope.row.resource_id }}</span></template></el-table-column><el-table-column label="处理链" min-width="280"><template #default="scope">{{ processorFor(scope.row.resource_type) }}</template></el-table-column><el-table-column prop="pipeline_version" label="流水线版本" min-width="145" /><el-table-column label="状态" width="110"><template #default="scope"><el-tag :type="scope.row.status === 'COMPLETED' ? 'success' : 'warning'" effect="plain">{{ scope.row.status === 'COMPLETED' ? '已完成' : '待处理' }}</el-tag></template></el-table-column><el-table-column label="质量" width="100"><template #default="scope">{{ scope.row.quality_status }}</template></el-table-column><el-table-column label="操作" width="120"><template #default="scope"><el-button link type="primary" :disabled="scope.row.status === 'COMPLETED'" @click="runPreprocess(scope.row)">执行预处理</el-button></template></el-table-column>
        </el-table></el-card>
      </el-tab-pane>

      <el-tab-pane label="质量异常" name="quality">
        <el-empty v-if="qualityRows.length === 0" description="当前没有阻断性质量异常" />
        <el-card v-else class="workspace-card" shadow="never"><el-table :data="qualityRows"><el-table-column prop="resource_id" label="资源编号" /><el-table-column label="异常"><template #default>元数据不完整</template></el-table-column><el-table-column label="操作"><template #default="scope"><el-button link type="primary" @click="inspect(scope.row)">查看</el-button></template></el-table-column></el-table></el-card>
      </el-tab-pane>
    </el-tabs>

    <el-dialog v-model="uploadVisible" title="上传巡检资源" width="min(600px, 94vw)" destroy-on-close>
      <el-form label-position="top"><div class="form-grid"><el-form-item label="巡检任务"><el-select v-model="uploadForm.task_id" filterable><el-option v-for="item in taskRows" :key="item.task_id" :label="`${item.task_id} / ${item.line_id}`" :value="item.task_id" /></el-select></el-form-item><el-form-item label="资源类型"><el-select v-model="uploadForm.resource_type"><el-option v-for="item in resourceTypes" :key="item.value" :label="item.label" :value="item.value" /><el-option label="视频" value="video" /><el-option label="飞行日志" value="flight_log" /></el-select></el-form-item></div><el-form-item label="资源文件"><el-upload drag :auto-upload="false" :limit="1" :on-change="selectFile" :on-remove="removeFile"><el-icon class="el-icon--upload"><UploadFilled /></el-icon><div class="el-upload__text">拖放文件或点击选择</div><template #tip><div class="el-upload__tip">使用 8 MB 分片上传，支持失败后按分片重试</div></template></el-upload></el-form-item><el-progress v-if="uploading" :percentage="uploadProgress" :stroke-width="8" /></el-form>
      <template #footer><el-button @click="uploadVisible = false">取消</el-button><el-button type="primary" :loading="uploading" @click="uploadResource">上传并校验</el-button></template>
    </el-dialog>

    <el-drawer v-model="detailVisible" title="数据资源预览" size="560px">
      <el-skeleton v-if="detailLoading" :rows="8" animated />
      <template v-else><div class="resource-preview" :class="`preview-${detail.preview_type || 'file'}`"><el-icon><Picture v-if="detail.preview_type === 'image'" /><Histogram v-else-if="detail.preview_type === 'thermal'" /><Grid v-else /></el-icon><strong>{{ typeLabel(detail.resource_type) }}</strong><span>{{ fileName(detail.storage_url) }}</span></div><el-descriptions :column="1" border><el-descriptions-item label="资源编号"><span class="entity-id">{{ detail.resource_id }}</span></el-descriptions-item><el-descriptions-item label="来源任务">{{ detail.task_id }}</el-descriptions-item><el-descriptions-item label="存储地址">{{ detail.storage_url }}</el-descriptions-item><el-descriptions-item label="元数据">{{ metadataSummary(detail.metadata) }}</el-descriptions-item></el-descriptions></template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import type { UploadFile } from "element-plus";
import { ElMessage } from "element-plus";
import { Grid, Histogram, Picture, Refresh, Search, Upload, UploadFilled } from "@element-plus/icons-vue";
import PageHeader from "../../components/common/PageHeader.vue";
import { preprocessJobs, resourcePreview, resources, runPreprocessJob, tasks, uploadInspectionFile } from "../../services/api";
import { safeObject, statusLabel, statusTag, type Row } from "../../types/demo-run";

const route = useRoute(); const router = useRouter(); const loading = ref(false); const rows = ref<Row[]>([]); const preprocessRows = ref<Row[]>([]); const taskRows = ref<Row[]>([]); const activeTab = ref(String(route.query.tab || "library")); const keyword = ref(""); const typeFilter = ref("");
const detailVisible = ref(false); const detailLoading = ref(false); const detail = ref<Row>({});
const uploadVisible = ref(false); const uploading = ref(false); const uploadProgress = ref(0); const uploadFile = ref<File | null>(null); const uploadForm = reactive({ task_id: "", resource_type: "image" });
const resourceTypes = [{ value: "image", label: "可见光" }, { value: "thermal", label: "红外" }, { value: "pointcloud", label: "点云" }, { value: "tif", label: "TIF/DEM" }];
const processors = [{ key: "image", type: "可见光", steps: "畸变校正 / 质量检查 / 标准化" }, { key: "thermal", type: "红外", steps: "温度标定 / 坏点修复 / 辐射校正" }, { key: "pointcloud", type: "点云", steps: "去噪 / 配准 / 分割 / 坐标转换" }, { key: "tif", type: "TIF/DEM", steps: "投影校验 / 重采样 / 高程转换" }];
const filteredRows = computed(() => rows.value.filter((row) => (!typeFilter.value || row.resource_type === typeFilter.value) && (!route.query.taskId || row.task_id === route.query.taskId) && (!keyword.value || `${row.resource_id} ${row.task_id} ${row.storage_url}`.toLowerCase().includes(keyword.value.toLowerCase()))));
const qualityRows = computed(() => rows.value.filter((row) => row.quality_status && row.quality_status !== "PASSED"));
const metrics = computed(() => [{ label: "资源总数", value: rows.value.length, note: "全部接入数据" }, ...resourceTypes.map((item) => ({ label: item.label, value: typeCount(item.value), note: "已完成入库" })), { label: "质量异常", value: qualityRows.value.length, note: "需要人工检查" }]);
function typeCount(type: string) { return rows.value.filter((row) => row.resource_type === type).length; }
function typeLabel(type: unknown) { return resourceTypes.find((item) => item.value === String(type))?.label || String(type || "文件"); }
function fileName(path: unknown) { return String(path || "-").split("/").pop() || "-"; }
function metadataSummary(value: unknown) { const data = safeObject(value); return Object.entries(data).slice(0, 2).map(([key, item]) => `${key}: ${item}`).join("，") || "无扩展元数据"; }
function processorFor(type: unknown) { return processors.find((item) => item.key === String(type))?.steps || "格式校验 / 标准化"; }
function formatDateTime(value: unknown) { return value ? new Date(String(value)).toLocaleString("zh-CN", { hour12: false }) : "-"; }
async function load() { loading.value = true; try { [rows.value, preprocessRows.value, taskRows.value] = await Promise.all([resources(), preprocessJobs(), tasks()]); if (!uploadForm.task_id && taskRows.value.length) uploadForm.task_id = String(taskRows.value[0].task_id); const id = String(route.params.resourceId || ""); if (id) { const row = rows.value.find((item) => String(item.resource_id) === id); if (row) inspect(row); } } finally { loading.value = false; } }
function selectFile(file: UploadFile) { uploadFile.value = file.raw || null; }
function removeFile() { uploadFile.value = null; }
async function uploadResource() { if (!uploadForm.task_id || !uploadFile.value) return ElMessage.warning("请选择巡检任务和资源文件"); uploading.value = true; uploadProgress.value = 0; try { const result = await uploadInspectionFile(uploadForm.task_id, uploadFile.value, uploadForm.resource_type, (value) => uploadProgress.value = value); await runPreprocessJob(String(result.preprocess_job_id)); ElMessage.success("资源已分片上传、摘要校验并完成基础预处理"); uploadVisible.value = false; uploadFile.value = null; activeTab.value = "preprocess"; await load(); } finally { uploading.value = false; } }
async function runPreprocess(row: Row) { await runPreprocessJob(String(row.preprocess_job_id)); ElMessage.success("预处理与质量检查已完成"); await load(); }
async function inspect(row: Row) { detailVisible.value = true; detailLoading.value = true; router.replace({ path: `/resources/${row.resource_id}`, query: route.query }); try { detail.value = await resourcePreview(String(row.resource_id)); } finally { detailLoading.value = false; } }
watch(detailVisible, (visible) => { if (!visible && route.params.resourceId) router.replace({ path: "/resources", query: route.query }); });
onMounted(load);
</script>
