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

// Moved mechanically from scripts/src/artifact-registry.ts:3448-3700 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 { d601K3sGuardShellLines } from "../d601-k3s-guard";
import { composeRuntimeEnvValue } from "../runtime-env";

import type { ArtifactRegistryAction, ArtifactRegistryCommandRuntime, ArtifactRegistryOptions } from "./types";
import { renderBundle } from "./bundle";
import { deployBackendCoreJob, deployBackendCoreNow, deployComposeArtifactNow, deployD601ComposeArtifactNow, dryRunArtifactConsumerPlan, legacyDeployBackendCoreResult } from "./compose-deploy";
import { artifactConsumerLiveBlock, artifactConsumerSpec, artifactConsumerTarget, supportedArtifactConsumers, unsupportedEnvironment, unsupportedService } from "./consumer";
import { install, installDryRun } from "./install";
import { deployD601K3sArtifactNow, rollbackInfo } from "./k3s-deploy";
import { isHelpArg, parseArtifactRegistryOptions } from "./options";
import { runReadonlyStatusWithRemoteFallback } from "./readonly";
import { plan } from "./status";
import { defaultOptions, legacyDeployBackendCoreDisabled, supportedArtifactConsumerServices } from "./types";

export async function deployServiceNow(options: ArtifactRegistryOptions): Promise<Record<string, unknown>> {
  if (options.serviceId === null) throw new Error("artifact-registry deploy-service requires --service <id>");
  if (options.commit === null) throw new Error("artifact-registry deploy-service requires --commit <full-sha>");
  const spec = artifactConsumerSpec(options.serviceId, options.environment);
  if (spec === null) return unsupportedService(options.serviceId, options);
  const target = artifactConsumerTarget(spec, options.environment);
  if (target === null) return unsupportedEnvironment(spec, options);
  if (options.dryRun) return dryRunArtifactConsumerPlan(options, spec, target, options.commit);
  const liveBlock = artifactConsumerLiveBlock(spec, options);
  if (liveBlock !== null) return liveBlock;
  if (spec.kind === "compose") return deployComposeArtifactNow(options, spec, target);
  if (spec.kind === "d601-compose") return deployD601ComposeArtifactNow(options, spec, target);
  return deployD601K3sArtifactNow(options, spec, target);
}

export function deployServiceJob(args: string[], options: ArtifactRegistryOptions): Record<string, unknown> {
  if (options.serviceId === null) throw new Error("artifact-registry deploy-service requires --service <id>");
  if (options.commit === null) throw new Error("artifact-registry deploy-service requires --commit <full-sha>");
  const spec = artifactConsumerSpec(options.serviceId, options.environment);
  if (spec === null) return unsupportedService(options.serviceId, options);
  const target = artifactConsumerTarget(spec, options.environment);
  if (target === null) return unsupportedEnvironment(spec, options);
  if (options.dryRun) return dryRunArtifactConsumerPlan(options, spec, target, options.commit);
  const liveBlock = artifactConsumerLiveBlock(spec, options);
  if (liveBlock !== null) return liveBlock;
  const runArgs = args.includes("--run-now") ? args : [...args, "--run-now"];
  const command = [process.execPath, rootPath("scripts", "cli.ts"), "artifact-registry", ...runArgs];
  const job = startJob("artifact_registry_service_cd", command, `Pull and deploy ${options.environment ?? "prod"} ${options.serviceId} artifact ${options.commit} from D601 registry`);
  return {
    ok: true,
    mode: "async-job",
    serviceId: options.serviceId,
    environment: options.environment ?? "prod",
    job,
    statusCommand: `bun scripts/cli.ts job status ${job.id}`,
    tailCommand: `bun scripts/cli.ts job status ${job.id} --tail-bytes 30000`,
    note: "User-service CD continues in the background: D601 registry health, commit-pinned artifact check, pull/import, rollout, image-label and live health commit verification.",
    rollback: rollbackInfo(spec, target, options.environment ?? "prod", options.commit),
  };
}

export function serviceIdFromDeployBackendCoreArgs(action: ArtifactRegistryAction, options: ArtifactRegistryOptions): string | null {
  return action === "deploy-backend-core" ? "backend-core" : options.serviceId;
}

export function localHelp(): Record<string, unknown> {
  return {
    ok: true,
    command: "artifact-registry plan|render|status|health|install|deploy-backend-core|deploy-service",
    output: "json",
    usage: [
      "bun scripts/cli.ts artifact-registry plan [--target D601]",
      "bun scripts/cli.ts artifact-registry render [--target D601]",
      "bun scripts/cli.ts artifact-registry status [--target D601]",
      "bun scripts/cli.ts artifact-registry health [--target D601]",
      "bun scripts/cli.ts artifact-registry install [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --service baidu-netdisk --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --service frontend --env prod --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --service frontend --env dev --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service project-manager --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service oa-event-flow --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service met-nonlinear --commit <full-sha> --dry-run [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service met-nonlinear --commit <full-sha> --dry-run [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service k3sctl-adapter --commit <full-sha> --dry-run [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env prod --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
      "bun scripts/cli.ts artifact-registry deploy-service --env dev --service code-queue --commit <full-sha> --dry-run [--target D601]",
    ],
    firstStage: "install now writes the rendered systemd/Compose/config files and starts the registry",
    artifactConsumers: {
      supportedServices: supportedArtifactConsumerServices,
      supportedConsumers: supportedArtifactConsumers(),
      unsupportedPolicy: "return structured unsupported; never fall back to legacy maintenance-channel source builds",
      prodCommands: [
        "bun scripts/cli.ts deploy apply --env prod --service backend-core",
        "bun scripts/cli.ts deploy apply --env prod --service baidu-netdisk",
        "bun scripts/cli.ts deploy apply --env prod --service frontend",
        "bun scripts/cli.ts deploy apply --env prod --service decision-center",
        "bun scripts/cli.ts deploy apply --env prod --service project-manager",
        "bun scripts/cli.ts deploy apply --env prod --service oa-event-flow",
        "bun scripts/cli.ts deploy apply --env prod --service code-queue-mgr --dry-run",
        "bun scripts/cli.ts deploy apply --env prod --service todo-note",
        "bun scripts/cli.ts deploy apply --env prod --service findjob",
        "bun scripts/cli.ts deploy apply --env prod --service pipeline",
        "bun scripts/cli.ts deploy apply --env prod --service met-nonlinear --dry-run",
        "bun scripts/cli.ts deploy apply --env prod --service k3sctl-adapter --dry-run",
        "bun scripts/cli.ts deploy apply --env prod --service mdtodo",
        "bun scripts/cli.ts deploy apply --env prod --service claudeqq",
      ],
      devCommands: [
        "bun scripts/cli.ts deploy apply --env dev --service frontend",
        "bun scripts/cli.ts deploy apply --env dev --service decision-center",
        "bun scripts/cli.ts deploy apply --env dev --service project-manager --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service oa-event-flow --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service code-queue-mgr --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service todo-note",
        "bun scripts/cli.ts deploy apply --env dev --service findjob --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service pipeline --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service met-nonlinear --dry-run",
        "bun scripts/cli.ts deploy apply --env dev --service mdtodo",
        "bun scripts/cli.ts deploy apply --env dev --service claudeqq",
        "bun scripts/cli.ts deploy apply --env dev --service code-queue --dry-run",
      ],
      devOnlyConsumers: ["code-queue"],
      rollbackShape: "rerun the same artifact consumer with a previous commit-pinned image",
    },
    legacyEntrypoints: {
      "deploy-backend-core": {
        deprecated: true,
        enabled: !legacyDeployBackendCoreDisabled,
        replacement: "bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>",
      },
    },
    defaults: defaultOptions,
  };
}

export async function runArtifactRegistryCommand(args: string[], runtime: ArtifactRegistryCommandRuntime = {}): Promise<unknown> {
  const action = args[0];
  if (isHelpArg(action)) return localHelp();
  if (action !== "plan" && action !== "render" && action !== "status" && action !== "health" && action !== "install" && action !== "deploy-backend-core" && action !== "deploy-service") {
    throw new Error("artifact-registry usage: plan|render|status|health|install|deploy-backend-core|deploy-service");
  }
  const typedAction = action as ArtifactRegistryAction;
  const options = parseArtifactRegistryOptions(args.slice(1));
  if (action === "plan") return plan(options);
  if (action === "render") return { ok: true, providerId: options.providerId, render: renderBundle(options) };
  if (action === "status") return runReadonlyStatusWithRemoteFallback(options, false, runtime);
  if (action === "health") return runReadonlyStatusWithRemoteFallback(options, true, runtime);
  if (action === "install") {
    return options.dryRun ? installDryRun(options) : install(options);
  }
  if (action === "deploy-backend-core") {
    if (options.commit === null) throw new Error("artifact-registry deploy-backend-core requires --commit <full-sha>");
    if (legacyDeployBackendCoreDisabled) return legacyDeployBackendCoreResult(options);
    return options.runNow ? await deployBackendCoreNow(options) : deployBackendCoreJob(args, options);
  }
  if (action === "deploy-service") {
    const serviceId = serviceIdFromDeployBackendCoreArgs(typedAction, options);
    return options.runNow || options.dryRun ? await deployServiceNow({ ...options, serviceId }) : deployServiceJob(args, { ...options, serviceId });
  }
  throw new Error("unreachable artifact-registry action");
}
