// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. apply-status-scripts module for scripts/src/platform-infra-observability.ts.

// Moved mechanically from scripts/src/platform-infra-observability.ts:1300-1574 for #903.

// SPEC: PJ2026-01060501 OTel追踪 draft-2026-06-19-p0.
// Responsibility: YAML-first platform-infra OpenTelemetry tracing control commands.
import { Buffer } from "node:buffer";
import { readFileSync } from "node:fs";
import type { UniDeskConfig } from "../config";
import { rootPath } from "../config";
import type { RenderedCliResult } from "../output";
import {
  compactCapture,
  createYamlFieldReader,
  numberField,
  parseJsonOutput,
  redactSensitiveUnknown,
  shQuote,
  capture,
} from "../platform-infra-ops-library";

import { isoFromUnixNano, shortenEnd, textValue } from "./manifest";
import { trace } from "./render";
import { asArray, limitArray } from "./trace-script";

export function compactSearchTrace(value: unknown): Record<string, unknown> {
  const trace = asPlainRecord(value) ?? {};
  const meta = compactMetaRecord(trace.meta);
  const startTimeUnixNano = trace.startTimeUnixNano ?? meta?.startTimeUnixNano ?? null;
  return {
    traceId: trace.traceId ?? null,
    startAt: isoFromUnixNano(startTimeUnixNano),
    durationMs: trace.durationMs ?? meta?.durationMs ?? null,
    traceCommand: trace.traceCommand ?? null,
    grepCommand: trace.grepCommand ?? null,
    meta,
    queryOk: trace.queryOk ?? null,
    parseOk: trace.parseOk ?? null,
    rawMatched: trace.rawMatched ?? null,
    matchingActive: trace.matchingActive ?? null,
    bodyBytes: trace.bodyBytes ?? null,
    spanCount: trace.spanCount ?? null,
    serviceCount: trace.serviceCount ?? null,
    services: trace.services ?? null,
    businessTraceIds: trace.businessTraceIds ?? null,
    errorSpanCount: trace.errorSpanCount ?? null,
    matchedSpanCount: trace.matchedSpanCount ?? null,
    spanNameCounts: compactNameCounts(trace.spanNameCounts, 6),
    errorSpanNames: compactSpanNames(trace.errorSpans, 5),
    matchedSpanNames: compactSpanNames(trace.matchedSpans, 8),
    stderrTail: trace.stderrTail ?? null,
  };
}

export function compactDiagnoseCodeAgentResult(value: unknown): Record<string, unknown> {
  const source = asPlainRecord(value) ?? {};
  const mapping = asPlainRecord(source.mapping);
  const evidence = asPlainRecord(source.evidence);
  return {
    ok: source.ok === true,
    mapping: mapping === null ? null : {
      mode: mapping.mode ?? null,
      businessTraceId: mapping.businessTraceId ?? null,
      runId: mapping.runId ?? null,
      commandId: mapping.commandId ?? null,
      runnerJobId: mapping.runnerJobId ?? null,
      otelTraceId: mapping.otelTraceId ?? null,
      searchQuery: mapping.searchQuery ?? null,
      searchOk: mapping.searchOk ?? null,
      searchParseOk: mapping.searchParseOk ?? null,
      candidateTraceCount: mapping.candidateTraceCount ?? null,
      scannedCandidateCount: mapping.scannedCandidateCount ?? null,
      candidateSelectionMode: mapping.candidateSelectionMode ?? null,
      selectedScore: mapping.selectedScore ?? null,
      selectedQuality: mapping.selectedQuality ?? null,
      selectedLowConfidence: mapping.selectedLowConfidence ?? null,
      selectedRejectedReason: mapping.selectedRejectedReason ?? null,
      selectedReasons: limitArray(mapping.selectedReasons, 4),
      selectedMeta: compactMetaRecord(mapping.selectedMeta),
      bestCandidate: asArray(mapping.candidatePreview).slice(0, 1).map(compactDiagnoseCandidate)[0] ?? null,
      searchStderrTail: mapping.searchStderrTail ?? null,
    },
    tracePath: source.tracePath ?? null,
    bodyBytes: source.bodyBytes ?? null,
    traceParseOk: source.traceParseOk ?? null,
    spanCount: source.spanCount ?? null,
    services: source.services ?? null,
    servicePath: source.servicePath ?? null,
    businessTraceIds: source.businessTraceIds ?? null,
    identity: compactDiagnoseIdentity(source.identity),
    agentrun: compactDiagnoseAgentRun(source.agentrun),
    hwlabReadModel: source.hwlabReadModel ?? null,
    http: compactDiagnoseHttp(source.http),
    projectionLag: source.projectionLag ?? null,
    summary: source.summary ?? null,
    rootCauseCandidates: asArray(source.rootCauseCandidates).slice(0, 3).map(compactRootCauseCandidate),
    spanNameCounts: compactNameCounts(source.spanNameCounts, 6),
    evidence: evidence === null ? null : {
      httpProblemSpanCount: evidence.httpProblemSpanCount ?? null,
      terminalSpanCount: evidence.terminalSpanCount ?? null,
      turnStatusReadSpanCount: evidence.turnStatusReadSpanCount ?? null,
      projectionSpanCount: evidence.projectionSpanCount ?? null,
      errorSpanCount: evidence.errorSpanCount ?? null,
      errorSpanSampleNames: evidence.errorSpanSampleNames ?? null,
      idleWarningSpanCount: evidence.idleWarningSpanCount ?? null,
      idleWarningSpanTail: compactSpanList(evidence.idleWarningSpanTail, 1),
    },
    next: compactDiagnoseNext(source.next),
    stderrTail: source.stderrTail ?? null,
    disclosure: {
      defaultView: "compact diagnosis; --full is bounded JSON, not a span dump",
      expand: "use trace --grep <span> --full for span evidence; use diagnose-code-agent --raw only for parser/envelope debugging",
    },
  };
}

export function compactDiagnoseIdentity(value: unknown): Record<string, unknown> | null {
  return compactRecord(value, [
    "runId",
    "commandId",
    "sessionId",
    "turnId",
    "runnerJobId",
    "runnerId",
    "backendProfile",
    "sourceCommit",
    "jobName",
    "namespace",
  ]);
}

export function compactDiagnoseHttp(value: unknown): Record<string, unknown> | null {
  const http = asPlainRecord(value);
  if (http === null) return null;
  return {
    problemCounts: http.problemCounts ?? null,
    problemSpanCount: http.problemSpanCount ?? null,
    statusCounts: asArray(http.statusCounts).slice(0, 4),
  };
}

export function compactDiagnoseAgentRun(value: unknown): Record<string, unknown> | null {
  const agentrun = asPlainRecord(value);
  if (agentrun === null) return null;
  return {
    terminalStatus: agentrun.terminalStatus ?? null,
    terminalSource: agentrun.terminalSource ?? null,
    latestSeq: agentrun.latestSeq ?? null,
    terminalEventType: agentrun.terminalEventType ?? null,
    failureKind: agentrun.failureKind ?? null,
    observedFailureKinds: limitArray(agentrun.observedFailureKinds, 5),
    runnerProviderClassification: agentrun.runnerProviderClassification ?? null,
    authority: compactAgentRunAuthority(agentrun.authority),
  };
}

export function compactAgentRunAuthority(value: unknown): Record<string, unknown> | null {
  const authority = asPlainRecord(value);
  if (authority === null) return null;
  const result: Record<string, unknown> = {
    queried: authority.queried ?? null,
    namespace: authority.namespace ?? null,
    ok: authority.ok ?? null,
    commandOk: authority.commandOk ?? null,
    resultOk: authority.resultOk ?? null,
    eventsOk: authority.eventsOk ?? null,
    commandState: authority.commandState ?? null,
    commandStatus: authority.commandStatus ?? null,
    resultTerminalStatus: authority.resultTerminalStatus ?? null,
    resultStatus: authority.resultStatus ?? null,
    terminalStatus: authority.terminalStatus ?? null,
    terminalSource: authority.terminalSource ?? null,
    terminalEventSeq: authority.terminalEventSeq ?? null,
    terminalEventType: authority.terminalEventType ?? null,
    failureKind: authority.failureKind ?? null,
    latestSeq: authority.latestSeq ?? null,
    eventCount: authority.eventCount ?? null,
    fallback: authority.fallback ?? null,
    error: authority.error ?? null,
    warnings: limitArray(authority.warnings, 3),
  };
  const ok = authority.ok === true && authority.commandOk === true && authority.resultOk === true && authority.eventsOk === true;
  if (!ok) {
    result.attempts = compactAgentRunAuthorityAttempts(authority.attempts);
  }
  return result;
}

export function compactAgentRunAuthorityAttempts(value: unknown): unknown[] {
  return asArray(value).slice(0, 3).map((item) => {
    const attempt = asPlainRecord(item) ?? {};
    return {
      name: attempt.name ?? attempt.section ?? attempt.kind ?? null,
      ok: attempt.ok ?? null,
      status: attempt.status ?? null,
      exitCode: attempt.exitCode ?? null,
      url: attempt.url ?? null,
      error: shortenEnd(textValue(attempt.error), 240),
      stderrTail: shortenEnd(textValue(attempt.stderrTail ?? attempt.stderr), 500),
    };
  });
}

export function compactDiagnoseCandidate(value: unknown): Record<string, unknown> {
  const candidate = asPlainRecord(value) ?? {};
  return {
    traceId: candidate.traceId ?? null,
    score: candidate.score ?? null,
    reasons: limitArray(candidate.reasons, 3),
    parseOk: candidate.parseOk ?? null,
    queryOk: candidate.queryOk ?? null,
    spanCount: candidate.spanCount ?? null,
    services: candidate.services ?? null,
    servicePath: candidate.servicePath ?? null,
    identity: compactDiagnoseIdentity(candidate.identity),
    terminalStatus: candidate.terminalStatus ?? null,
    errorSpanCount: candidate.errorSpanCount ?? null,
    candidateQuality: candidate.candidateQuality ?? null,
    lowConfidence: candidate.lowConfidence ?? null,
    spanNamePreview: limitArray(candidate.spanNamePreview, 4),
  };
}

export function compactDiagnoseNext(value: unknown): Record<string, unknown> | null {
  const next = asPlainRecord(value);
  if (next === null) return null;
  return {
    diagnoseFull: next.diagnoseFull ?? null,
    traceSummary: next.traceSummary ?? null,
    traceReads: next.traceReads ?? null,
  };
}

export function compactRootCauseCandidate(value: unknown): Record<string, unknown> {
  const candidate = asPlainRecord(value) ?? {};
  return {
    code: candidate.code ?? null,
    label: candidate.label ?? null,
    confidence: candidate.confidence ?? null,
    summary: candidate.summary ?? null,
    evidenceCount: Array.isArray(candidate.evidence) ? candidate.evidence.length : candidate.evidence === undefined || candidate.evidence === null ? 0 : 1,
  };
}

export function compactSpanList(value: unknown, limit: number): unknown[] {
  return asArray(value).slice(0, limit).map((item) => {
    const span = asPlainRecord(item) ?? {};
    const attrs = asPlainRecord(span.attributes) ?? {};
    return {
      name: span.name ?? null,
      service: span.service ?? null,
      attributes: compactRecord(attrs, ["failureKind", "terminalStatus", "status", "eventType", "idleMs", "waitingFor", "lastEventLabel", "http.route", "http.status_code", "http.response.status_code", "workbench.session_id", "workbench.trace_id", "workbench.turn_id", "workbench.read_model.route", "workbench.read_model.count", "workbench.read_model.family", "workbench.read_model.status", "workbench.read_model.reason", "hwlab.http.stage", "hwlab.http.phase", "hwlab.http.phase.outcome", "hwlab.live_builds.service_id", "hwlab.live_builds.service_kind", "hwlab.live_builds.external", "hwlab.live_builds.deploy_manifest_status", "hwlab.live_builds.artifact_catalog_status"]),
    };
  });
}

export function compactSpanNames(value: unknown, limit: number): string[] {
  return asArray(value).slice(0, limit).map((item) => {
    const span = asPlainRecord(item);
    return String(span?.name ?? "<unknown>");
  });
}

export function compactNameCounts(value: unknown, limit: number): unknown[] {
  return asArray(value).slice(0, limit).map((item) => {
    const record = asPlainRecord(item) ?? {};
    return { name: record.name ?? null, count: record.count ?? null };
  });
}

export function compactMetaRecord(value: unknown): Record<string, unknown> | null {
  return compactRecord(value, ["traceID", "traceId", "rootServiceName", "rootTraceName", "startTimeUnixNano", "durationMs"]);
}

export function compactRecord(value: unknown, keys: string[]): Record<string, unknown> | null {
  const source = asPlainRecord(value);
  if (source === null) return null;
  const result: Record<string, unknown> = {};
  for (const key of keys) {
    if (Object.prototype.hasOwnProperty.call(source, key)) result[key] = source[key];
  }
  return result;
}

export function asPlainRecord(value: unknown): Record<string, unknown> | null {
  if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
  return value as Record<string, unknown>;
}
