<template>
  <section class="full-chain-console">
    <el-card shadow="never">
      <template #header>
        <div class="run-console-title">
          <div>
            <h2>全链路运行工作台</h2>
            <p>{{ run.activeRunId.value || "尚未创建运行实例" }}</p>
          </div>
          <div class="run-controls">
            <span class="connection-state" :class="`connection-${connectionClass}`"><i></i>{{ connectionLabel }}</span>
            <el-tooltip content="导出运行记录" placement="top"><el-button :icon="Download" circle :disabled="!run.activeRunId.value" @click="handleExport" /></el-tooltip>
            <el-button v-if="run.running.value" :icon="Close" plain @click="handleCancel">取消运行</el-button>
            <el-button type="primary" :icon="VideoPlay" :loading="starting || run.running.value" @click="handleStart">{{ run.activeRunId.value ? "重新运行" : "启动全链路" }}</el-button>
          </div>
        </div>
      </template>

      <div class="global-run-state">
        <div>
          <el-tag :type="runStatusTag" effect="dark">{{ runStatusText }}</el-tag>
          <strong>{{ displayedTitle }}</strong>
          <span>{{ displayedMessage }}</span>
        </div>
        <div class="global-progress"><el-progress :percentage="run.runProgress.value" :stroke-width="12" :status="progressStatus" /><small>当前节点：{{ currentStageName }}</small></div>
      </div>

      <RunStageNavigator :stages="run.stages.value" :selected-step-key="run.displayedStepKey.value" @select="run.selectStep" />

      <div v-if="!run.followRun.value" class="history-notice">
        <span>正在查看历史节点，实时运行已推进至“{{ currentStageName }}”。</span>
        <el-button link type="primary" @click="run.followCurrent">回到当前节点</el-button>
      </div>

      <div class="run-workspace">
        <RunGisMap
          :step-key="run.displayedStepKey.value"
          :step-snapshots="run.stepSnapshots.value"
          :selected-entity-id="selectedEntity.id"
          @select="handleMapSelect"
        />
        <div class="step-workspace">
          <component
            :is="activeStepComponent"
            :snapshot="run.displayedStep.value"
            @retry="handleRetry"
            @inspect="handleInspect"
            @locate="handleLocate"
            @redispatch="handleRedispatch"
            @review="handleReview"
            @sample-decision="handleSampleDecision"
          />
        </div>
      </div>

      <RunEvidenceTabs
        :events="run.events.value"
        :current-step-key="run.displayedStepKey.value"
        :step-snapshots="run.stepSnapshots.value"
        @inspect="handleInspect"
        @select-step="run.selectStep"
      />
    </el-card>

    <el-drawer v-model="detailVisible" :title="detailTitle" size="520px">
      <el-skeleton v-if="detailLoading" :rows="8" animated />
      <template v-else>
        <el-descriptions :column="1" border>
          <el-descriptions-item v-for="item in detailItems" :key="item.label" :label="item.label">{{ item.value }}</el-descriptions-item>
        </el-descriptions>
        <pre v-if="detailJson" class="detail-json">{{ detailJson }}</pre>
      </template>
    </el-drawer>
  </section>
</template>

<script setup lang="ts">
import { computed, markRaw, reactive, ref, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Close, Download, VideoPlay } from "@element-plus/icons-vue";
import { alarmEvidence, decideSample, demoRunExportUrl, redispatchWorkorder, resourcePreview, resultEvidence, reviewWorkorder } from "../../services/api";
import { useDemoRun } from "../../composables/useDemoRun";
import { formatValue, RUN_STAGES, safeObject, type Row } from "../../types/demo-run";
import RunStageNavigator from "./RunStageNavigator.vue";
import RunGisMap from "./RunGisMap.vue";
import RunEvidenceTabs from "./RunEvidenceTabs.vue";
import RunInitializationPanel from "./steps/RunInitializationPanel.vue";
import InspectionTaskPanel from "./steps/InspectionTaskPanel.vue";
import UavDispatchPanel from "./steps/UavDispatchPanel.vue";
import ResourceIngestionPanel from "./steps/ResourceIngestionPanel.vue";
import PreprocessPipelinePanel from "./steps/PreprocessPipelinePanel.vue";
import InferenceWorkspacePanel from "./steps/InferenceWorkspacePanel.vue";
import RuleEvaluationPanel from "./steps/RuleEvaluationPanel.vue";
import AlarmGenerationPanel from "./steps/AlarmGenerationPanel.vue";
import WorkorderDispatchPanel from "./steps/WorkorderDispatchPanel.vue";
import WorkorderClosurePanel from "./steps/WorkorderClosurePanel.vue";
import SampleFeedbackPanel from "./steps/SampleFeedbackPanel.vue";
import RunSummaryPanel from "./steps/RunSummaryPanel.vue";

const props = defineProps<{ initialRunId?: string }>();
const emit = defineEmits<{ refresh: [] }>();
const run = useDemoRun(async () => emit("refresh"));
const starting = ref(false);
const selectedEntity = reactive({ type: "", id: "" });
const detailVisible = ref(false);
const detailLoading = ref(false);
const detailTitle = ref("实体详情");
const detailData = ref<Row>({});

watch(() => props.initialRunId, async (runId) => {
  if (!runId || runId === run.activeRunId.value) return;
  try { await run.open(runId); } catch { ElMessage.error("运行记录加载失败"); }
}, { immediate: true });

const componentMap: Record<string, any> = {
  "run.initializing": markRaw(RunInitializationPanel),
  "task.created": markRaw(InspectionTaskPanel),
  "uav.dispatching": markRaw(UavDispatchPanel),
  "resource.ingesting": markRaw(ResourceIngestionPanel),
  "preprocess.running": markRaw(PreprocessPipelinePanel),
  "ai.inferencing": markRaw(InferenceWorkspacePanel),
  "rule.evaluating": markRaw(RuleEvaluationPanel),
  "alarm.generating": markRaw(AlarmGenerationPanel),
  "workorder.dispatching": markRaw(WorkorderDispatchPanel),
  "workorder.closing": markRaw(WorkorderClosurePanel),
  "sample.feedback": markRaw(SampleFeedbackPanel),
  "run.completed": markRaw(RunSummaryPanel)
};

const activeStepComponent = computed(() => componentMap[run.displayedStepKey.value] || RunInitializationPanel);
const currentStageName = computed(() => RUN_STAGES.find((stage) => stage.key === run.currentStepKey.value)?.name || "等待启动");
const displayedTitle = computed(() => run.displayedStep.value.title || currentStageName.value);
const displayedMessage = computed(() => run.displayedStep.value.message || "启动运行后，系统将在此展示各节点的输入、处理过程、输出和业务操作。" );
const runStatusText = computed(() => ({ idle: "待启动", running: "运行中", completed: "运行完成", failed: "运行失败", cancelled: "已取消" } as Record<string, string>)[String(run.snapshot.value?.status || "idle")] || "待启动");
const runStatusTag = computed<"success" | "danger" | "warning" | "info" | "primary">(() => ({ completed: "success", failed: "danger", cancelled: "warning", running: "primary", idle: "info" } as any)[String(run.snapshot.value?.status || "idle")] || "info");
const progressStatus = computed<"" | "success" | "exception" | "warning">(() => {
  const status = String(run.snapshot.value?.status || "");
  if (status === "completed") return "success";
  if (status === "failed") return "exception";
  if (status === "cancelled") return "warning";
  return "";
});
const connectionClass = computed(() => ["completed", "failed", "cancelled"].includes(String(run.snapshot.value?.status)) ? "idle" : run.connectionStatus.value);
const connectionLabel = computed(() => {
  const status = String(run.snapshot.value?.status || "idle");
  if (status === "completed") return "事件已归档";
  if (status === "failed" || status === "cancelled") return "运行已结束";
  return ({ idle: "未连接", connected: "实时连接", reconnecting: "正在重连", disconnected: "连接断开" } as Record<string, string>)[run.connectionStatus.value];
});
const detailItems = computed(() => Object.entries(detailData.value).filter(([, value]) => !value || typeof value !== "object").map(([label, value]) => ({ label, value: formatValue(value) })).slice(0, 18));
const detailJson = computed(() => {
  const nested = Object.fromEntries(Object.entries(detailData.value).filter(([, value]) => value && typeof value === "object"));
  return Object.keys(nested).length ? JSON.stringify(nested, null, 2) : "";
});

async function handleStart() {
  if (run.running.value) return;
  starting.value = true;
  try {
    await run.start();
    ElMessage.success("全链路运行已启动");
  } catch {
    ElMessage.error("全链路运行启动失败");
  } finally {
    starting.value = false;
  }
}

async function handleCancel() {
  try {
    await ElMessageBox.confirm("取消后将保留已完成节点和业务数据，确认继续？", "取消运行", { type: "warning" });
    await run.cancel();
    ElMessage.warning("取消请求已提交");
  } catch {
    // User dismissed the confirmation.
  }
}

async function handleRetry() {
  try {
    await run.retry();
    ElMessage.success("节点重试已启动");
  } catch (error: any) {
    ElMessage.error(error?.response?.data?.message || "节点重试失败");
  }
}

async function handleInspect(entity: { type: string; id: string }) {
  if (!entity.id) return;
  selectedEntity.type = entity.type;
  selectedEntity.id = entity.id;
  detailVisible.value = true;
  detailLoading.value = true;
  detailTitle.value = ({ resource: "数据资源详情", result: "AI 结果证据", alarm: "告警证据链" } as Record<string, string>)[entity.type] || "实体详情";
  try {
    if (entity.type === "resource") detailData.value = await resourcePreview(entity.id);
    else if (entity.type === "result") detailData.value = await resultEvidence(entity.id);
    else if (entity.type === "alarm") detailData.value = await alarmEvidence(entity.id);
    else detailData.value = { entity_type: entity.type, entity_id: entity.id };
  } catch {
    detailData.value = { entity_type: entity.type, entity_id: entity.id, status: "详情加载失败" };
  } finally {
    detailLoading.value = false;
  }
}

function handleLocate(entity: { type: string; id: string }) {
  selectedEntity.type = entity.type;
  selectedEntity.id = entity.id;
  ElMessage.success("已在 GIS 中定位关联对象");
}

function handleMapSelect(entity: { type: string; id: string }) {
  selectedEntity.type = entity.type;
  selectedEntity.id = entity.id;
  if (["resource", "result", "alarm"].includes(entity.type)) handleInspect(entity);
}

async function handleRedispatch(workorder: Row) {
  await redispatchWorkorder(String(workorder.workorder_id));
  patchEntity("workorders", String(workorder.workorder_id), { status: "created", dispatch_status: "delivered" });
  ElMessage.success("工单已重新派发");
  emit("refresh");
}

async function handleReview(workorder: Row, action: "approve" | "return") {
  await reviewWorkorder(String(workorder.workorder_id), action);
  patchEntity("workorders", String(workorder.workorder_id), { status: action === "approve" ? "closed" : "processing", close_result: action === "approve" ? "复核通过" : "退回重办" });
  ElMessage.success(action === "approve" ? "工单已复核闭环" : "工单已退回重办");
  emit("refresh");
}

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

function patchEntity(collection: string, id: string, patch: Row) {
  Object.values(run.stepSnapshots.value).forEach((snapshot) => {
    const visual = safeObject(snapshot.visual_payload);
    const rows = visual[collection];
    if (!Array.isArray(rows)) return;
    const index = rows.findIndex((row: Row) => String(row.workorder_id || row.sample_id || row.id) === id);
    if (index >= 0) rows[index] = { ...rows[index], ...patch };
  });
}

function handleExport() {
  if (!run.activeRunId.value) return;
  window.open(demoRunExportUrl(run.activeRunId.value), "_blank", "noopener,noreferrer");
}

defineExpose({ start: handleStart, cancel: handleCancel, running: run.running });
</script>
