/*
 * SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-18-p0-unique-projection; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0.
 * 职责: WorkbenchProjectionFinalizer 组件入口。以 checkpoint/轮询驱动 AgentRun facts 追平，不让 GET path 承担 finalize/repair。
 */
import { appendProjectionDiagnostic } from "./workbench-projection-writer.ts";

export function scheduleWorkbenchProjectionFinalizer({ traceId, currentResult = null, traceStore, getCachedResult, isCanceled, isTerminal, syncResult, onTerminal, activitySignature, noResponseTimeoutMs = null, pollIntervalMs = 1000, sleep = defaultSleep, performanceStore = null } = {}) {
  if (!traceId || !currentResult?.agentRun?.runId || !currentResult?.agentRun?.commandId || typeof syncResult !== "function") return null;
  let lastActivityAt = Date.now();
  let lastActivitySignature = activitySignature?.(currentResult, traceStore?.snapshot?.(traceId)) ?? null;
  let idleDegraded = false;
  performanceStore?.recordWorkbenchProjectorCandidate?.({ status: "scheduled", reason: "finalizer" });

  setImmediate(() => {
    void (async () => {
      let result = currentResult;
      let lastError = null;
      while (true) {
        const cached = getCachedResult?.(traceId);
        if (isCanceled?.(cached)) return;
        if (cached && isTerminal?.(cached, traceStore?.snapshot?.(traceId))) {
          performanceStore?.recordWorkbenchProjectorCandidate?.({ status: "completed", reason: "cached_terminal" });
          onTerminal?.(cached, { preserveLastTraceId: true });
          return;
        }
        const syncStartedAt = Date.now();
        try {
          const synced = await syncResult({ result });
          performanceStore?.recordWorkbenchProjectorBatch?.({ phase: "candidate_scan", status: "ok", durationMs: Date.now() - syncStartedAt });
          result = synced?.result ?? result;
          const runnerTrace = synced?.runnerTrace ?? traceStore?.snapshot?.(traceId);
          if (result && isTerminal?.(result, runnerTrace)) {
            performanceStore?.recordWorkbenchProjectorCandidate?.({ status: "completed", reason: "synced_terminal" });
            onTerminal?.(result, { preserveLastTraceId: true });
            return;
          }
          const signature = activitySignature?.(result, runnerTrace);
          if (signature && signature !== lastActivitySignature) {
            lastActivitySignature = signature;
            lastActivityAt = Date.now();
            idleDegraded = false;
          }
          lastError = null;
        } catch (error) {
          performanceStore?.recordWorkbenchProjectorBatch?.({ phase: "candidate_scan", status: error?.code === "agentrun_timeout" ? "timeout" : "error", durationMs: Date.now() - syncStartedAt });
          performanceStore?.recordWorkbenchProjectorError?.({ reason: error?.code ?? "finalizer_sync_failed" });
          lastError = error;
        }
        const idleMs = Date.now() - lastActivityAt;
        if (noResponseTimeoutMs && idleMs >= noResponseTimeoutMs && !idleDegraded) {
          performanceStore?.recordWorkbenchProjectorCandidate?.({ status: "degraded", reason: "no_response_idle_timeout" });
          performanceStore?.recordWorkbenchProjectorError?.({ reason: lastError?.code ?? "no_response_idle_timeout" });
          appendProjectionDiagnostic(traceStore, traceId, {
            type: "turn-status",
            status: "degraded",
            label: "projection-finalizer:no-response-idle-timeout",
            errorCode: lastError?.code ?? "no_response_idle_timeout",
            degradedReason: lastError ? "projection_activity_stale" : "no_response_idle_timeout",
            message: lastError?.message ?? `AgentRun projection has no new activity for ${idleMs}ms; idle threshold ${noResponseTimeoutMs}ms.`,
            runId: result?.agentRun?.runId ?? currentResult.agentRun.runId,
            commandId: result?.agentRun?.commandId ?? currentResult.agentRun.commandId,
            timeoutMs: noResponseTimeoutMs,
            idleMs,
            lastActivityAt: new Date(lastActivityAt).toISOString(),
            waitingFor: "agentrun-result-activity",
            terminal: false
          });
          idleDegraded = true;
        }
        await sleep(pollIntervalMs);
      }
    })().catch((error) => {
      performanceStore?.recordWorkbenchProjectorError?.({ reason: error?.code ?? "workbench_projection_finalizer_crashed" });
      appendProjectionDiagnostic(traceStore, traceId, {
        type: "turn-status",
        status: "degraded",
        label: "projection-finalizer:sync-crashed",
        errorCode: error?.code ?? "workbench_projection_finalizer_crashed",
        message: error?.message ?? "Workbench projection finalizer crashed.",
        runId: currentResult.agentRun.runId,
        commandId: currentResult.agentRun.commandId,
        waitingFor: "agentrun-result",
        terminal: false
      });
    });
  });
  return { scheduled: true, traceId, noResponseTimeoutMs, pollIntervalMs, valuesPrinted: false };
}

function defaultSleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, Math.max(0, Number(ms) || 0)));
}
