<script setup lang="ts">
// SPEC: PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0
// Starts Workbench first-screen journey timing around route hydrate.

import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import CommandComposer from "@/components/workbench/CommandComposer.vue";
import ConversationPanel from "@/components/workbench/ConversationPanel.vue";
import SessionRail from "@/components/workbench/SessionRail.vue";
import WorkbenchKafkaDebugPanel from "@/components/workbench/WorkbenchKafkaDebugPanel.vue";
import { useAutoRefresh } from "@/composables/useAutoRefresh";
import { shouldReflectWorkbenchSessionUrl } from "@/router/workbench-navigation";
import { workbenchDebugCapabilities } from "@/config/runtime";
import { useAuthStore } from "@/stores/auth";
import { useWorkbenchStore } from "@/stores/workbench";
import { workbenchCurrentDebugTraceId } from "@/stores/workbench-isolated-kafka-debug";
import { normalizeWorkbenchSessionId, normalizeWorkbenchSessionRouteId } from "@/utils";
import { finishWorkbenchOpenFullLoad, startWorkbenchOpenJourney } from "@/utils/workbench-performance";

const workbench = useWorkbenchStore();
const auth = useAuthStore();
const debugCapabilities = workbenchDebugCapabilities();
const route = useRoute();
const router = useRouter();
const routeRequestId = computed(() => normalizeWorkbenchSessionRouteId(route.params.sessionId));
const rawRouteSessionId = computed(() => typeof route.params.sessionId === "string" ? route.params.sessionId.trim() : "");
const routeReflectionTarget = computed(() => routeRequestId.value ?? (rawRouteSessionId.value || null));
const applyingRouteSession = ref(Boolean(rawRouteSessionId.value));
const componentActive = ref(false);
const isolatedDebugOpen = ref(false);
const isolatedDebugAvailable = computed(() => auth.isAdmin && (debugCapabilities.isolatedKafka || debugCapabilities.rawHwlabEventWindow.enabled));
const isolatedDebugTraceId = computed(() => workbenchCurrentDebugTraceId(workbench.activeMessages, workbench.activeSession?.lastTraceId));
type LaunchContextRecord = {
  sourceId?: string | null;
  hwpodId?: string | null;
  mdtodoRootRef?: string | null;
  workspaceRootLabel?: string | null;
  executionContext?: LaunchContextRecord | null;
};
const workbenchLaunchContext = computed(() => {
  const context = (workbench.activeSession?.launchContext ?? null) as LaunchContextRecord | null;
  if (!context) return null;
  const execution = context.executionContext ?? context;
  const sourceId = execution.sourceId ?? context.sourceId ?? null;
  const hwpodId = execution.hwpodId ?? context.hwpodId ?? null;
  if (!sourceId && !hwpodId) return null;
  return {
    sourceId,
    hwpodId,
    mdtodoRootRef: execution.mdtodoRootRef ?? context.mdtodoRootRef ?? null,
    workspaceRootLabel: execution.workspaceRootLabel ?? context.workspaceRootLabel ?? null
  };
});

onMounted(async () => {
  componentActive.value = true;
  applyingRouteSession.value = Boolean(rawRouteSessionId.value);
  const hydratedRouteTarget = routeReflectionTarget.value;
  startWorkbenchOpenJourney({ route: route.path, cache: routeRequestId.value ? "cold" : "warm", authState: "warm" });
  try {
    await workbench.hydrate({ sessionId: routeRequestId.value, invalidRouteId: rawRouteSessionId.value && !routeRequestId.value ? rawRouteSessionId.value : null });
    if (routeReflectionTarget.value !== hydratedRouteTarget) await applyRouteSession();
    finishWorkbenchOpenFullLoad(workbench.error ? "error" : "ok");
  } finally {
    applyingRouteSession.value = false;
  }
  if (!routeRequestId.value && !rawRouteSessionId.value) await reflectActiveSessionInUrl(workbench.activeSessionId);
});
onBeforeUnmount(() => {
  componentActive.value = false;
});
watch(() => route.params.sessionId, () => void applyRouteSession());
watch(() => workbench.activeSessionId, (sessionId) => void reflectActiveSessionInUrl(sessionId));
watch(isolatedDebugAvailable, (available) => { if (!available) isolatedDebugOpen.value = false; });
useAutoRefresh(refreshLiveWhenIdle, 120_000, { immediate: false, initialDelayMs: 90_000 });

async function refreshLiveWhenIdle(): Promise<void> {
  if (workbench.loading || workbench.sessionListLoading || workbench.sessionDetailLoading || workbench.chatPending) return;
  await workbench.refreshLive();
}

async function applyRouteSession(): Promise<boolean> {
  const sessionId = routeRequestId.value;
  if (!sessionId && !rawRouteSessionId.value) return true;
  applyingRouteSession.value = true;
  let selected = false;
  try {
    selected = sessionId ? await workbench.selectSessionById(sessionId, null, { source: "route" }) : await workbench.selectSessionById(rawRouteSessionId.value, null, { source: "route" });
    return selected;
  } finally {
    applyingRouteSession.value = false;
    if (selected) await reflectActiveSessionInUrl(workbench.activeSessionId);
  }
}

async function reflectActiveSessionInUrl(value: string | null): Promise<void> {
  const sessionId = normalizeWorkbenchSessionId(value);
  const routeTarget = routeReflectionTarget.value;
  if (!shouldReflectWorkbenchSessionUrl({
    componentActive: componentActive.value,
    routeName: route.name,
    routePath: route.path,
    routeSection: route.meta.section,
    routeSessionId: routeTarget,
    sessionId,
    activeSelectionSource: workbench.activeSessionSelectionSource,
    applyingRouteSession: applyingRouteSession.value
  })) return;
  await router.replace({
    name: "CodeWorkbenchSession",
    params: { sessionId },
    query: {}
  });
}
</script>

<template>
  <section id="workspace" class="workbench-route">
    <div class="workbench-grid">
      <SessionRail />
      <main class="workbench-center" :class="{ 'has-launch-context': workbenchLaunchContext }">
        <div v-if="workbenchLaunchContext" class="workbench-context-strip" data-testid="workbench-launch-context">
          <span>Source: {{ workbenchLaunchContext.sourceId || '-' }}</span>
          <span v-if="workbenchLaunchContext.hwpodId">HWPOD: {{ workbenchLaunchContext.hwpodId }}</span>
          <span v-if="workbenchLaunchContext.mdtodoRootRef">MDTODO: {{ workbenchLaunchContext.mdtodoRootRef }}</span>
          <span v-if="workbenchLaunchContext.workspaceRootLabel">Workspace: {{ workbenchLaunchContext.workspaceRootLabel }}</span>
        </div>
        <div
          class="workbench-conversation-stack"
          :data-debug-control="isolatedDebugAvailable ? 'true' : 'false'"
          :data-debug-open="isolatedDebugOpen ? 'true' : 'false'"
        >
          <div v-if="isolatedDebugAvailable" class="workbench-isolated-debug-toggle">
            <label>
              <input v-model="isolatedDebugOpen" data-testid="workbench-kafka-debug-toggle" type="checkbox" />
              <span>Kafka 调试观察模式</span>
            </label>
            <small>{{ isolatedDebugTraceId ? `当前 trace ${isolatedDebugTraceId}` : "等待当前 traceId" }}</small>
          </div>
          <ConversationPanel />
          <WorkbenchKafkaDebugPanel
            v-if="isolatedDebugOpen"
            :trace-id="isolatedDebugTraceId"
            :replay-enabled="debugCapabilities.isolatedKafka"
            :raw-enabled="debugCapabilities.rawHwlabEventWindow.enabled"
            :raw-ingress="workbench.rawHwlabIngress"
            :on-clear-raw-ingress="workbench.clearRawHwlabIngress"
          />
        </div>
        <CommandComposer />
      </main>
    </div>
  </section>
</template>

<style scoped>
.workbench-conversation-stack {
  display: grid;
  min-width: 0;
  min-height: 0;
  grid-template-rows: minmax(0, 1fr);
  overflow: hidden;
}

.workbench-conversation-stack[data-debug-control="true"] {
  grid-template-rows: auto minmax(0, 1fr);
}

.workbench-conversation-stack[data-debug-open="true"] {
  grid-template-rows: auto minmax(180px, 1fr) minmax(250px, 0.8fr);
}

.workbench-isolated-debug-toggle {
  display: flex;
  min-width: 0;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid #ddd6fe;
  background: #f7f5ff;
  padding: 6px 10px;
  color: #4c1d95;
  font-size: 12px;
}

.workbench-isolated-debug-toggle label {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 7px;
  font-weight: 750;
}

.workbench-isolated-debug-toggle small {
  min-width: 0;
  overflow: hidden;
  color: #6d28d9;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 720px) {
  .workbench-conversation-stack[data-debug-open="true"] {
    grid-template-rows: auto minmax(140px, 0.7fr) minmax(250px, 1fr);
  }
}
</style>
