// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. artifact-probe module for scripts/src/artifact-registry.ts.

// Moved mechanically from scripts/src/artifact-registry.ts:2391-2578 for #903.

import { createHash } from "node:crypto";
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { runCommand, type CommandResult } from "../command";
import { readConfig, type UniDeskConfig, repoRoot, rootPath } from "../config";
import { startJob } from "../jobs";
import {
  compareDeployJsonExecutorMirrors,
  deployJsonCommitImage,
  deployJsonDriftResult,
  deployJsonSourceOfTruth,
  hasDeployJsonExecutorContract,
  k3sManifestExecutorMirror,
  parseDeployJsonServiceContractBase64,
  readDeployJsonServiceContractFromFile,
  type DeployJsonExecutorMirror,
  type DeployJsonServiceContract,
} from "../deploy-json-contract";
import { k3sGuardShellLines } from "../k3s-target-guard";
import { composeRuntimeEnvValue } from "../runtime-env";

import type { ArtifactConsumerSpec, ArtifactConsumerTarget, ArtifactRegistryOptions } from "./types";
import { base64, k3sTargetGuardScript, shellQuote } from "./bundle";
import { artifactImageRef, deployRefFor, sourceRepoFor } from "./consumer";

export function registryArtifactProbeScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, commit: string): string {
  const sourceImage = artifactImageRef(options, spec, commit);
  return [
    "set -euo pipefail",
    `registry_image=${shellQuote(sourceImage)}`,
    `manifest_url=${shellQuote(`http://127.0.0.1:${options.port}/v2/${spec.registryRepository}/manifests/${commit}`)}`,
    "headers=$(mktemp /tmp/unidesk-artifact-manifest.XXXXXX.headers)",
    "trap 'rm -f \"$headers\"' EXIT",
    "curl -fsSI -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' -D \"$headers\" -o /dev/null \"$manifest_url\"",
    "manifest_digest=$(awk 'BEGIN{IGNORECASE=1} /^Docker-Content-Digest:/ {gsub(/\\r/, \"\", $2); print $2; exit}' \"$headers\")",
    "printf 'registry_image=%s\\nmanifest_url=%s\\nmanifest_digest=%s\\n' \"$registry_image\" \"$manifest_url\" \"$manifest_digest\"",
  ].join("\n");
}

export function registryArtifactMissingMessage(spec: ArtifactConsumerSpec): string {
  return `${spec.serviceId} image artifact is missing from D601 registry; run CI artifact publication first`;
}

export function verifyLocalArtifactLabels(
  localLoadedImage: string,
  spec: ArtifactConsumerSpec,
  commit: string,
  sourceRepo: string,
): Record<string, unknown> | null {
  const inspectPulled = runCommand(["docker", "image", "inspect", localLoadedImage, "--format", "{{json .Config.Labels}}"], repoRoot);
  const labelCommit = runCommand(["docker", "image", "inspect", localLoadedImage, "--format", "{{ index .Config.Labels \"unidesk.ai/source-commit\" }}"], repoRoot);
  const labelService = runCommand(["docker", "image", "inspect", localLoadedImage, "--format", "{{ index .Config.Labels \"unidesk.ai/service-id\" }}"], repoRoot);
  const labelRepo = runCommand(["docker", "image", "inspect", localLoadedImage, "--format", "{{ index .Config.Labels \"unidesk.ai/source-repo\" }}"], repoRoot);
  const labelDockerfile = runCommand(["docker", "image", "inspect", localLoadedImage, "--format", "{{ index .Config.Labels \"unidesk.ai/dockerfile\" }}"], repoRoot);
  const observed = {
    commit: labelCommit.stdout.trim(),
    serviceId: labelService.stdout.trim(),
    sourceRepo: labelRepo.stdout.trim(),
    dockerfile: labelDockerfile.stdout.trim(),
    labels: inspectPulled.stdout.trim(),
  };
  const ok = observed.commit === commit
    && observed.serviceId === spec.serviceId
    && observed.sourceRepo === sourceRepo
    && observed.dockerfile === spec.dockerfile;
  if (ok) return null;
  return {
    ok: false,
    step: "image-label-verify",
    expected: { commit, serviceId: spec.serviceId, sourceRepo, dockerfile: spec.dockerfile },
    observed,
  };
}

export function devFrontendAuthPatchScript(config: UniDeskConfig): string {
  const sshClientToken = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_TOKEN");
  if (sshClientToken === null) throw new Error(`UNIDESK_SSH_CLIENT_TOKEN must be present in ${rootPath(".state", "docker-compose.env")} before deploying dev frontend`);
  const sshClientRouteAllowlist = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST") ?? "G14,G14:*,D601,D601:*";
  const secretData = {
    AUTH_USERNAME: base64(config.auth.username),
    AUTH_PASSWORD: base64(config.auth.password),
    SESSION_SECRET: base64(config.auth.sessionSecret),
    UNIDESK_SSH_CLIENT_TOKEN: base64(sshClientToken),
  };
  const configData = {
    SESSION_TTL_SECONDS: String(config.auth.sessionTtlSeconds),
    UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST: sshClientRouteAllowlist,
  };
  return [
    k3sTargetGuardScript(),
    `secret_patch=${shellQuote(JSON.stringify({ data: secretData }))}`,
    `config_patch=${shellQuote(JSON.stringify({ data: configData }))}`,
    "kubectl -n unidesk-dev patch secret unidesk-dev-runtime-secrets --type merge -p \"$secret_patch\"",
    "kubectl -n unidesk-dev patch configmap unidesk-dev-runtime-config --type merge -p \"$config_patch\"",
    "echo artifact_cd_dev_frontend_auth_synced=ok",
  ].join("\n");
}

export function composeArtifactEnvValues(spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget, options: ArtifactRegistryOptions, commit: string): Record<string, string> {
  if (target.compose === undefined) throw new Error(`${spec.serviceId} missing compose artifact consumer config`);
  const prefix = target.compose.deployEnvPrefix;
  return {
    [`${prefix}_SERVICE_ID`]: spec.serviceId,
    [`${prefix}_REF`]: deployRefFor(options, spec),
    [`${prefix}_REPO`]: sourceRepoFor(options, spec),
    [`${prefix}_COMMIT`]: commit,
    [`${prefix}_REQUESTED_COMMIT`]: commit,
  };
}

export function syntheticComposeHealthDeployScript(compose: NonNullable<ArtifactConsumerTarget["compose"]>, commit: string, sourceRepo: string): string[] {
  if (compose.syntheticHealthDeployProof === undefined) return [];
  const prefix = compose.deployEnvPrefix;
  const envKeys = [
    "UNIDESK_DEPLOY_SERVICE_ID",
    "UNIDESK_DEPLOY_REF",
    "UNIDESK_DEPLOY_REPO",
    "UNIDESK_DEPLOY_COMMIT",
    "UNIDESK_DEPLOY_REQUESTED_COMMIT",
    `${prefix}_SERVICE_ID`,
    `${prefix}_REF`,
    `${prefix}_REPO`,
    `${prefix}_COMMIT`,
    `${prefix}_REQUESTED_COMMIT`,
  ];
  const envKeysJson = JSON.stringify(envKeys);
  return [
    "runtime_metadata_json=$(docker inspect \"$cid\" --format '{{json .Config.Env}}')",
    "container_label_commit=$(docker inspect -f '{{ index .Config.Labels \"unidesk.ai/deploy-commit\" }}' \"$cid\")",
    "container_label_requested_commit=$(docker inspect -f '{{ index .Config.Labels \"unidesk.ai/deploy-requested-commit\" }}' \"$cid\")",
    "container_label_repo=$(docker inspect -f '{{ index .Config.Labels \"unidesk.ai/deploy-repo\" }}' \"$cid\")",
    "container_label_ref=$(docker inspect -f '{{ index .Config.Labels \"unidesk.ai/deploy-ref\" }}' \"$cid\")",
    `python3 - "$health_json" "$runtime_metadata_json" ${shellQuote(envKeysJson)} ${shellQuote(prefix)} ${shellQuote(commit)} ${shellQuote(sourceRepo)} "$actual_commit" "$actual_service" "$actual_repo" "$container_label_commit" "$container_label_requested_commit" "$container_label_repo" "$container_label_ref" <<'PY'`,
    "import json, sys",
    "path, env_json, keys_json, prefix, expected_commit, expected_repo, image_commit, image_service, image_repo, label_commit, label_requested_commit, label_repo, label_ref = sys.argv[1:]",
    "body = json.load(open(path, encoding='utf-8'))",
    "env_items = json.loads(env_json)",
    "allow = set(json.loads(keys_json))",
    "env = {}",
    "for item in env_items:",
    "    if not isinstance(item, str) or '=' not in item:",
    "        continue",
    "    key, value = item.split('=', 1)",
    "    if key in allow:",
    "        env[key] = value",
    "deploy = body.get('deploy') if isinstance(body, dict) and isinstance(body.get('deploy'), dict) else {}",
    "synthetic = {",
    "    'serviceId': deploy.get('serviceId') or env.get('UNIDESK_DEPLOY_SERVICE_ID') or env.get(prefix + '_SERVICE_ID') or image_service,",
    "    'ref': deploy.get('ref') or env.get('UNIDESK_DEPLOY_REF') or env.get(prefix + '_REF') or label_ref,",
    "    'repo': deploy.get('repo') or env.get('UNIDESK_DEPLOY_REPO') or env.get(prefix + '_REPO') or label_repo or image_repo,",
    "    'commit': deploy.get('commit') or env.get('UNIDESK_DEPLOY_COMMIT') or env.get(prefix + '_COMMIT') or label_commit or image_commit,",
    "    'requestedCommit': deploy.get('requestedCommit') or env.get('UNIDESK_DEPLOY_REQUESTED_COMMIT') or env.get(prefix + '_REQUESTED_COMMIT') or label_requested_commit,",
    "}",
    "body['deploy'] = synthetic",
    "body['deployProof'] = {",
    "    'kind': 'compose-container-runtime-metadata',",
    "    'sources': ['service-health', 'container-env', 'container-labels', 'image-labels'],",
    "    'sourceDirectoryUsed': False,",
    "    'envKeysUsed': sorted([key for key in env if key.startswith('UNIDESK_DEPLOY_') or key.startswith(prefix + '_')]),",
    "}",
    "if synthetic.get('commit') != expected_commit or synthetic.get('requestedCommit') != expected_commit:",
    "    raise SystemExit('synthetic deploy commit mismatch: ' + json.dumps(synthetic, sort_keys=True))",
    "if synthetic.get('repo') != expected_repo:",
    "    raise SystemExit('synthetic deploy repo mismatch: ' + json.dumps(synthetic, sort_keys=True))",
    "if synthetic.get('serviceId') != image_service:",
    "    raise SystemExit('synthetic deploy service mismatch: ' + json.dumps(synthetic, sort_keys=True))",
    "with open(path, 'w', encoding='utf-8') as handle:",
    "    json.dump(body, handle, separators=(',', ':'))",
    "    handle.write('\\n')",
    "print('synthetic_health_deploy_proof=compose-container-runtime-metadata sourceDirectoryUsed=false')",
    "PY",
  ];
}
