// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. types module for scripts/src/platform-infra-observability.ts.
// SPEC: PJ2026-01060308 cicd-yaml-targets draft-2026-06-25-cicd-yaml-targets.

// Moved mechanically from scripts/src/platform-infra-observability.ts:1-149 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 { status } from "./actions";

export const configFile = rootPath("config", "platform-infra", "observability.yaml");

export const configLabel = "config/platform-infra/observability.yaml";

export const fieldManager = "unidesk-platform-observability";

export const {
  asRecord,
  objectField,
  arrayOfRecords,
  stringField,
  integerField,
  booleanField,
  stringArrayField,
  numberArrayField,
  enumField,
  kubernetesNameField,
  portField,
  apiPathField,
} = createYamlFieldReader(configLabel);

export interface ObservabilityConfig {
  version: number;
  kind: "platform-infra-observability";
  metadata: { id: string; owner: string; spec: string; relatedIssues: number[] };
  defaults: { targetId: string };
  images: {
    collector: ImageSpec;
    tempo: ImageSpec;
    prometheus: ImageSpec;
  };
  targets: ObservabilityTarget[];
  collector: {
    deploymentName: string;
    serviceName: string;
    configMapName: string;
    replicas: number;
    healthPort: number;
    otlp: OtlpPorts;
  };
  traceBackend: {
    type: "tempo";
    deploymentName: string;
    serviceName: string;
    configMapName: string;
    replicas: number;
    httpPort: number;
    otlp: OtlpPorts;
    storage: { mode: "emptyDir"; retention: string };
  };
  metricsBackend: PrometheusConfig;
  sampling: { mode: "parentbased_traceidratio"; ratio: number };
  instrumentation: {
    contextPropagation: string[];
    serviceConnections: ServiceConnection[];
  };
  resourceAttributes: {
    required: string[];
    businessCorrelationAttributes: string[];
  };
  probes: {
    readinessPath: string;
    traceQueryPathTemplate: string;
    statusEndpoints: StatusEndpoint[];
  };
}

export interface PrometheusConfig {
  type: "prometheus";
  enabled: boolean;
  targetIds: string[];
  deploymentName: string;
  serviceName: string;
  configMapName: string;
  serviceAccountName: string;
  clusterRoleName: string;
  clusterRoleBindingName: string;
  persistentVolumeClaimName: string;
  replicas: number;
  httpPort: number;
  storage: { mode: "persistentVolumeClaim"; size: string; retention: string };
  discovery: {
    namespaces: string[];
    labelSelector: { key: string; value: string };
    annotationKeys: { scrape: string; path: string; port: string };
    defaultPath: string;
    scrapeInterval: string;
    scrapeTimeout: string;
  };
  query: { path: string; timeoutSeconds: number; maxSeries: number; maxResponseBytes: number; maxCloseoutQueries: number };
}

export interface ImageSpec {
  repository: string;
  tag: string;
  pullPolicy: "Always" | "IfNotPresent" | "Never";
}

export interface ObservabilityTarget {
  id: string;
  route: string;
  namespace: string;
  role: "active" | "standby";
  enabled: boolean;
  createNamespace: boolean;
}

export interface OtlpPorts {
  grpcPort: number;
  httpPort: number;
}

export interface ServiceConnection {
  serviceName: string;
  owningRepo: string;
  targetNode: string;
  lane: string;
  namespace: string;
  configRefs: Record<string, string>;
  configRefGraph: Array<Record<string, unknown>>;
  requiredSpans: string[];
}

export interface StatusEndpoint {
  name: string;
  service: string;
  portName: string;
  path: string;
}

export interface CommonOptions {
  targetId: string | null;
  full: boolean;
  raw: boolean;
}

export interface ApplyOptions extends CommonOptions {
  confirm: boolean;
  dryRun: boolean;
  wait: boolean;
}

export interface TraceOptions extends CommonOptions {
  traceId: string | null;
  grep: string | null;
  limit: number;
}

export interface SearchOptions extends CommonOptions {
  grep: string | null;
  query: string | null;
  path: string | null;
  status: number | null;
  limit: number;
  candidateLimit: number;
  lookbackMinutes: number;
  endAt: string | null;
}

export interface DiagnoseCodeAgentOptions extends CommonOptions {
  businessTraceId: string | null;
  traceId: string | null;
  runId: string | null;
  commandId: string | null;
  sessionId: string | null;
  runnerJobId: string | null;
  limit: number;
  candidateLimit: number;
  lookbackMinutes: number;
}

export interface MetricsQueryOptions extends CommonOptions {
  query: string | null;
}

export interface CloseoutOptions extends CommonOptions {
  queries: string[];
  traceId: string | null;
  service: string | null;
}
