// 只读聚合 status、validate 以及调用者显式选择的 metrics/trace 证据。
import type { UniDeskConfig } from "../config";
import type { RenderedCliResult } from "../output";
import { redactSensitiveUnknown } from "../platform-infra-ops-library";
import { metricsQuery } from "./prometheus";
import { status, validate } from "./actions";
import { trace } from "./render";
import { formatTable, shortenEnd, textValue } from "./manifest";
import { resolveTarget } from "./actions";
import { readObservabilityConfig } from "./config";
import { targetSummary } from "./summary";
import type { CloseoutOptions } from "./types";

type Result = Record<string, unknown>;

export async function closeout(config: UniDeskConfig, options: CloseoutOptions): Promise<Result | RenderedCliResult> {
  const observability = readObservabilityConfig();
  const target = resolveTarget(observability, options.targetId);
  if (options.queries.length > observability.metricsBackend.query.maxCloseoutQueries) {
    throw new Error(`observability closeout accepts at most ${observability.metricsBackend.query.maxCloseoutQueries} --query values from config/platform-infra/observability.yaml`);
  }
  const operations: Array<Promise<Result>> = [
    settled("status", () => status(config, { targetId: target.id, full: true, raw: false })),
    settled("validate", () => validate(config, { targetId: target.id, full: true, raw: false })),
  ];
  for (const query of options.queries) {
    operations.push(settled(`metrics:${query}`, () => metricsQuery(config, { targetId: target.id, query, full: true, raw: false })));
  }
  if (options.traceId !== null) {
    operations.push(settled("trace", () => trace(config, {
      targetId: target.id,
      traceId: options.traceId,
      grep: options.service,
      limit: 40,
      full: true,
      raw: true,
    })));
  }
  const settledResults = await Promise.all(operations);
  const statusResult = settledResults[0];
  const validateResult = settledResults[1];
  const statusOk = statusResult.ok === true;
  const validateOk = validateResult.ok === true;
  const warnings = settledResults
    .filter((item) => item.ok !== true)
    .map((item) => ({ code: "observability-closeout-child-failed", operation: item.operation, blocking: false, detail: item.error ?? "child operation returned not-ok" }));
  const result: Result = {
    ok: statusOk && validateOk,
    action: "platform-infra-observability-closeout",
    mutation: false,
    blocking: false,
    target: targetSummary(target),
    requested: { queries: options.queries, traceId: options.traceId, service: options.service },
    status: redactSensitiveUnknown(statusResult),
    validate: redactSensitiveUnknown(validateResult),
    optional: settledResults.slice(2).map((item) => redactSensitiveUnknown(item)),
    warnings,
  };
  if (options.full || options.raw) return result;
  return renderCloseout(result, target.id, target.namespace);
}

async function settled(operation: string, run: () => Promise<unknown>): Promise<Result> {
  try {
    const value = await run();
    if (typeof value === "object" && value !== null && !Array.isArray(value)) {
      return { operation, ...(value as Result) };
    }
    return { operation, ok: false, error: "child operation returned an unsupported payload" };
  } catch (error) {
    return { operation, ok: false, error: error instanceof Error ? error.message : String(error) };
  }
}

function renderCloseout(result: Result, targetId: string, namespace: string): RenderedCliResult {
  const statusResult = asRecord(result.status);
  const validateResult = asRecord(result.validate);
  const optional = Array.isArray(result.optional) ? result.optional.filter(asRecord) : [];
  const rows = [
    ["status", textValue(statusResult?.ok)],
    ["validate", textValue(validateResult?.ok)],
    ...optional.map((item) => [textValue(item.operation), textValue(item.ok)]),
  ];
  const warnings = Array.isArray(result.warnings) ? result.warnings.filter(asRecord) : [];
  const lines = [
    `platform-infra observability closeout (${result.ok === true ? "ok" : "not-ok"})`,
    "",
    `target=${targetId} namespace=${namespace} ready=${result.ok === true} mutation=false blocking=false`,
    "",
    "Checks:",
    formatTable(["OPERATION", "OK"], rows.length > 0 ? rows : [["-", "-"]]),
  ];
  if (warnings.length > 0) {
    lines.push("", "Warnings:", formatTable(["OPERATION", "BLOCKING", "DETAIL"], warnings.map((item) => [shortenEnd(textValue(item.operation), 28), textValue(item.blocking), shortenEnd(textValue(item.detail), 100)])));
  }
  lines.push("", "Disclosure:", "  status/validate are always collected; metrics and trace are opt-in via --query/--trace-id.", "  Optional failures remain non-blocking warnings; use --full for structured child results.");
  return { ok: result.ok === true, command: "platform-infra observability closeout", contentType: "text/plain", renderedText: lines.join("\n") };
}

function asRecord(value: unknown): Result | null {
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Result : null;
}
