import { gitMirrorFlushJobManifest, gitMirrorStatusSummary, gitMirrorSyncJobManifest, gitMirrorV02SyncRequirement, hwlabG14Help, hwlabG14MonitorStateFileName, parseGitMirrorStatusRefs, parsePipelineTaskRunMetrics, rolloutRecordBody, semanticChangelogBullets, v02CommitAlignment, v02ControlPlaneRenderScript, v02FalseGreenGuard, v02PipelineServiceIds, v02TaskRunPerformanceSummary } from "./src/hwlab-g14";

function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
  if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
}

function record(value: unknown): Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : {};
}

assertCondition(
  hwlabG14MonitorStateFileName({ once: false, dryRun: false }) === "latest-monitor-job.json",
  "long-running monitor should own latest-monitor-job.json",
);
assertCondition(
  hwlabG14MonitorStateFileName({ once: true, dryRun: false }) === "latest-once-job.json",
  "once jobs must not overwrite the long-running monitor pointer",
);
assertCondition(
  hwlabG14MonitorStateFileName({ once: false, dryRun: true }) === "latest-dry-run-job.json",
  "dry-run monitor jobs must not overwrite the live monitor pointer",
);
assertCondition(
  hwlabG14MonitorStateFileName({ once: true, dryRun: true }) === "latest-once-dry-run-job.json",
  "once dry-runs need a distinct pointer for low-noise diagnostics",
);
const hwlabHelpUsage = Array.isArray(hwlabG14Help().usage) ? hwlabG14Help().usage.map(String) : [];
assertCondition(
  hwlabHelpUsage.some((line) => line.includes("control-plane status --lane v02 --pipeline-run"))
    && hwlabHelpUsage.some((line) => line.includes("control-plane status --lane v02 --source-commit")),
  "v0.2 control-plane status help must expose targeted PipelineRun/source-commit inspection",
  hwlabHelpUsage,
);

const gitMirrorJob = gitMirrorSyncJobManifest("git-mirror-hwlab-sync-manual-test");
assertCondition(gitMirrorJob.kind === "Job", "git mirror sync must be a manual Job, not a CronJob", gitMirrorJob);
assertCondition(record(gitMirrorJob.metadata).namespace === "devops-infra", "git mirror sync Job must target devops-infra", gitMirrorJob);
assertCondition(record(record(gitMirrorJob.metadata).labels)["hwlab.pikastech.local/trigger"] === "manual-cli", "git mirror sync Job must be labeled as manual CLI triggered", gitMirrorJob);
assertCondition(record(gitMirrorJob.spec).backoffLimit === 0, "git mirror sync Job should fail visibly instead of retrying in the background", gitMirrorJob);

const gitMirrorFlushJob = gitMirrorFlushJobManifest("git-mirror-hwlab-flush-manual-test");
assertCondition(gitMirrorFlushJob.kind === "Job", "git mirror flush must be a manual Job", gitMirrorFlushJob);
assertCondition(record(record(gitMirrorFlushJob.metadata).labels)["app.kubernetes.io/component"] === "flush-controller", "git mirror flush Job must be labeled separately from sync", gitMirrorFlushJob);
assertCondition(record(record(gitMirrorFlushJob.metadata).labels)["hwlab.pikastech.local/trigger"] === "manual-cli", "git mirror flush Job must be labeled as manual CLI triggered", gitMirrorFlushJob);
const flushTemplate = record(record(gitMirrorFlushJob.spec).template);
const flushPodSpec = record(flushTemplate.spec);
const flushContainer = record(Array.isArray(flushPodSpec.containers) ? flushPodSpec.containers[0] : null);
assertCondition(JSON.stringify(flushContainer.command) === JSON.stringify(["/script/flush.sh"]), "git mirror flush Job must run the flush script", gitMirrorFlushJob);

const gitMirrorStatusRaw = [
  'lastSync={"ok":true}',
  "lastWrite=",
  "lastFlush=",
  'refs={"refs":{"localV02":"0cf79ecc9d8a784b7712b0b3a58d5e39025ba0dc","githubV02":"0cf79ecc9d8a784b7712b0b3a58d5e39025ba0dc","localG14":"1111111111111111111111111111111111111111","githubG14":"1111111111111111111111111111111111111111","localGitops":"2222222222222222222222222222222222222222","githubGitops":"3333333333333333333333333333333333333333"},"pendingFlush":true}',
].join("\n");
const parsedGitMirrorRefs = parseGitMirrorStatusRefs(gitMirrorStatusRaw);
assertCondition(
  parsedGitMirrorRefs.refs.localV02 === "0cf79ecc9d8a784b7712b0b3a58d5e39025ba0dc",
  "git mirror status parser must expose local v0.2 ref for trigger pre-sync",
  parsedGitMirrorRefs,
);
assertCondition(parsedGitMirrorRefs.pendingFlush === true, "git mirror status parser must preserve pending flush signal", parsedGitMirrorRefs);
assertCondition(
  parsedGitMirrorRefs.refs.githubV02 === "0cf79ecc9d8a784b7712b0b3a58d5e39025ba0dc",
  "git mirror status parser must expose GitHub source branch staging ref",
  parsedGitMirrorRefs,
);
assertCondition(
  gitMirrorV02SyncRequirement("0cf79ecc9d8a784b7712b0b3a58d5e39025ba0dc", gitMirrorStatusRaw).required === false,
  "trigger-current must not sync mirror when local v0.2 already matches source commit",
);
assertCondition(
  gitMirrorV02SyncRequirement("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", gitMirrorStatusRaw).required === true,
  "trigger-current must sync mirror before creating PipelineRun when local v0.2 is stale",
);
const gitMirrorSummary = gitMirrorStatusSummary(gitMirrorStatusRaw);
assertCondition(
  gitMirrorSummary.flushNeeded === true && gitMirrorSummary.flushCommand === "bun scripts/cli.ts hwlab g14 git-mirror flush --confirm",
  "git mirror status summary must expose pending flush and the exact controlled flush command",
  gitMirrorSummary,
);
assertCondition(gitMirrorSummary.githubInSync === false, "git mirror status summary must expose GitHub GitOps drift", gitMirrorSummary);
assertCondition(gitMirrorSummary.sourceInSync === true && gitMirrorSummary.gitopsInSync === false, "git mirror status must split source and gitops GitHub sync state", gitMirrorSummary);
const renderScript = v02ControlPlaneRenderScript("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
assertCondition(
  renderScript.includes("git --git-dir=\"$cicd_repo\" worktree add --detach") && renderScript.includes("/tmp/hwlab-v02-control-plane-source-aaaaaaaaaaaa"),
  "v0.2 control-plane render must use a detached temp worktree from the CI/CD repo",
  renderScript,
);
assertCondition(
  renderScript.includes("cicd_repo='/root/hwlab-v02-cicd.git'") && !renderScript.includes("git -C /root/hwlab-v02") && !renderScript.includes("git checkout v0.2"),
  "v0.2 control-plane render must not use the fixed workspace checkout or its clean status",
  renderScript,
);
assertCondition(
  !v02PipelineServiceIds().includes("hwlab-cli"),
  "v0.2 PipelineRun service matrix must not build hwlab-cli because cli is short-connection source tool",
  v02PipelineServiceIds(),
);

const staleSuccessAlignment = v02CommitAlignment({
  expectedSourceHead: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  sourceHeads: {
    cicdRepo: "/root/hwlab-v02-cicd.git",
    cicdSourceHead: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    originHead: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    workspace: { path: "/root/hwlab-v02", head: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", originHead: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", dirty: true, dirtyCount: 1 },
  },
  gitMirrorSummary: { localV02: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", githubV02: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", sourceInSync: false, gitopsInSync: true },
  pipelineRun: { pipelineRun: "hwlab-v02-ci-poll-aaaaaaaaaaaa", status: null },
  recentPipelineRuns: { items: [{ name: "hwlab-v02-ci-poll-bbbbbbbbbbbb", sourceCommit: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", status: "True", reason: "Completed" }] },
  runtimeWorkloads: { items: [] },
  webAssets: { apiRevision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" },
});
assertCondition(
  staleSuccessAlignment.aligned === false
    && staleSuccessAlignment.state === "stale-success"
    && JSON.stringify(staleSuccessAlignment.staleReasons).includes("mirror-source-stale")
    && JSON.stringify(staleSuccessAlignment.workspaceWarnings).includes("workspace-dirty-but-isolated-from-cicd"),
  "v0.2 commit alignment must call out stale-success while keeping dirty workspace isolated from CI source selection",
  staleSuccessAlignment,
);

const falseGreenPassed = v02FalseGreenGuard({
  sourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  pipelineRun: { exists: true, status: "True" },
  taskRuns: {
    items: [
      { name: "hwlab-v02-ci-poll-aaaaaaaaaaaa-build-hwlab-cloud-api", status: "True" },
      { name: "hwlab-v02-ci-poll-aaaaaaaaaaaa-build-hwlab-cloud-web", status: "True" },
    ],
  },
  planArtifacts: {
    ok: true,
    buildServices: ["hwlab-cloud-api"],
    reusedServices: ["hwlab-cloud-web"],
    artifactProvenanceAudit: {
      ok: true,
      unsafeReuseServices: [],
    },
  },
  runtimeWorkloads: {
    ok: true,
    items: [
      { serviceId: "hwlab-cloud-api", artifactSourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" },
      { serviceId: "hwlab-cloud-web", artifactSourceCommit: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" },
    ],
  },
});
assertCondition(
  falseGreenPassed.ok === true && falseGreenPassed.state === "passed",
  "v0.2 false-green guard should pass when built runtime services and reuse provenance are proven",
  falseGreenPassed,
);

const falseGreenReuseMissingAudit = v02FalseGreenGuard({
  sourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  pipelineRun: { exists: true, status: "True" },
  taskRuns: { items: [{ name: "hwlab-v02-ci-poll-aaaaaaaaaaaa-build-hwlab-cloud-api", status: "True" }] },
  planArtifacts: {
    ok: true,
    buildServices: ["hwlab-cloud-api"],
    reusedServices: ["hwlab-cloud-web"],
    artifactProvenanceAudit: null,
  },
  runtimeWorkloads: { ok: true, items: [{ serviceId: "hwlab-cloud-api", artifactSourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }] },
});
assertCondition(
  falseGreenReuseMissingAudit.ok === true
    && JSON.stringify(falseGreenReuseMissingAudit.provenanceWarnings).includes("artifact-provenance-audit-missing-for-reuse"),
  "v0.2 false-green guard should not fail a completed rollout only because optional reuse provenance is missing",
  falseGreenReuseMissingAudit,
);

const falseGreenRuntimeMismatch = v02FalseGreenGuard({
  sourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  pipelineRun: { exists: true, status: "True" },
  taskRuns: { items: [{ name: "hwlab-v02-ci-poll-aaaaaaaaaaaa-build-hwlab-cloud-api", status: "True" }] },
  planArtifacts: {
    ok: true,
    buildServices: ["hwlab-cloud-api"],
    reusedServices: [],
    artifactProvenanceAudit: null,
  },
  runtimeWorkloads: { ok: true, items: [{ serviceId: "hwlab-cloud-api", artifactSourceCommit: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }] },
});
assertCondition(
  falseGreenRuntimeMismatch.ok === false
    && JSON.stringify(falseGreenRuntimeMismatch.failures).includes("artifact-source-commit-mismatch"),
  "v0.2 false-green guard must fail when a built service still runs an old artifact",
  falseGreenRuntimeMismatch,
);

const slowBuildSummary = v02TaskRunPerformanceSummary([
  {
    name: "hwlab-v02-ci-poll-f8a090b66616-build-hwlab-agent-worker",
    status: "True",
    reason: "Succeeded",
    durationSeconds: 234,
  },
  {
    name: "hwlab-v02-ci-poll-f8a090b66616-build-hwlab-cloud-web",
    status: "True",
    reason: "Succeeded",
    durationSeconds: 37,
  },
]);
const slowBuildItems = Array.isArray(record(slowBuildSummary).slowTaskRuns) ? record(slowBuildSummary).slowTaskRuns as Record<string, unknown>[] : [];
assertCondition(
  slowBuildSummary.ok === false
    && record(record(slowBuildSummary).thresholds).buildTaskRunWarningSeconds === 120
    && slowBuildItems.length === 1
    && slowBuildItems[0]?.serviceId === "hwlab-agent-worker"
    && slowBuildItems[0]?.severity === "critical",
  "v0.2 status must warn on slow build TaskRuns like issue #659",
  slowBuildSummary,
);

const prBody = [
  "## 背景",
  "",
  "G14 DEV Cloud Workbench 中，内部 `message-trace-body` 的 `pre` 会在 trace 更新时被替换，导致用户滚到中间后被重置到顶部。",
  "",
  "## 修改",
  "",
  "- trace row patch 从 index/replace 改为 stable `data-trace-row-id` keyed reconciliation。",
  "- 已存在 row 只移动和原地更新 header/body，不替换 `li/pre`。",
  "- `message-trace-body` 内部滚动状态按 `traceUiKey + rowId` 记忆。",
].join("\n");

const semanticBullets = semanticChangelogBullets("fix: preserve inner trace scroll", prBody, {
  keyFiles: [
    "modified web/hwlab-cloud-web/app.mjs",
    "modified web/hwlab-cloud-web/scripts/trace-scroll.test.mjs",
  ],
});

assertCondition(
  semanticBullets.some((line) => line.includes("修复目标") && line.includes("滚到中间后被重置到顶部")),
  "semantic changelog should explain the user-visible bug being fixed",
  semanticBullets,
);
assertCondition(
  semanticBullets.some((line) => line.includes("data-trace-row-id")),
  "semantic changelog should include PR body change bullets instead of only file stats",
  semanticBullets,
);

const summaryBullets = semanticChangelogBullets("feat: preload gateway tran helper", [
  "## 摘要",
  "- 新增 `/app/tools/hwlab-gateway-tran.mjs`，支持 `cmd`、`ps`、`upload`、`download`。",
].join("\n"), {});

assertCondition(
  summaryBullets.some((line) => line.includes("hwlab-gateway-tran.mjs") && line.includes("upload")),
  "semantic changelog should also extract Chinese summary sections",
  summaryBullets,
);

const rolloutBody = rolloutRecordBody({
  pr: { number: 506, title: "fix: preserve inner trace scroll", url: "https://github.com/pikasTech/HWLAB/pull/506" },
  prData: { json: { title: "fix: preserve inner trace scroll", body: prBody, url: "https://github.com/pikasTech/HWLAB/pull/506" } },
  fileSummary: {
    summary: { files: 2, additions: 268, deletions: 22, commits: 1 },
    keyFiles: [
      "modified web/hwlab-cloud-web/app.mjs",
      "modified web/hwlab-cloud-web/scripts/trace-scroll.test.mjs",
    ],
  },
  sourceCommit: "1a3fa9e6fbc987142463ecff2cbcef240a6278f2",
  pipelineRun: "hwlab-g14-ci-poll-1a3fa9e6fbc9",
  gitopsRevision: "21462b78ce4e7dba4ea374398f60db690e290147",
  mergedAt: "2026-05-27T06:52:22Z",
  pipelineSucceededAt: "2026-05-27T06:55:38Z",
  finishedAt: "2026-05-27T06:55:47Z",
  rollout: { pipelineText: "True\nSucceeded", argoText: "21462\nSynced\nHealthy\nSucceeded\n21462", healthOk: true },
  ciMetrics: parsePipelineTaskRunMetrics("hwlab-g14-ci-poll-test", [
    "taskrun-a\tbuild-hwlab-cloud-api\t2026-05-27T06:54:43Z\t2026-05-27T06:54:52Z\tservice-id=hwlab-cloud-api;status=reused;build-backend=reused-catalog;",
    "taskrun-b\tbuild-hwlab-cloud-web\t2026-05-27T06:54:43Z\t2026-05-27T06:55:08Z\tservice-id=hwlab-cloud-web;status=published;build-backend=buildkit;",
  ].join("\n")),
});

assertCondition(
  rolloutBody.includes("- 上线 changelog（语义化）:"),
  "rollout record must label natural-language changelog separately",
);
assertCondition(
  rolloutBody.includes("- 自动 diff 摘要:"),
  "rollout record must keep automatic diff summary separately",
);
assertCondition(
  rolloutBody.indexOf("- 上线 changelog（语义化）:") < rolloutBody.indexOf("- 自动 diff 摘要:"),
  "semantic changelog should appear before automatic diff summary",
);
assertCondition(
  rolloutBody.includes("changed files: 2; +268 / -22; commits: 1"),
  "automatic diff summary should preserve file/stat evidence",
);
assertCondition(
  rolloutBody.includes("lazy build reused: 1/2"),
  "rollout record should include lazy-build reused ratio",
  rolloutBody,
);
assertCondition(
  rolloutBody.includes("reused services: hwlab-cloud-api") && rolloutBody.includes("rebuild services: hwlab-cloud-web"),
  "rollout record should list reused and rebuild services",
  rolloutBody,
);
assertCondition(
  rolloutBody.includes("hwlab-cloud-api: reused, 9s") && rolloutBody.includes("hwlab-cloud-web: published, 25s"),
  "rollout record should include each service duration",
  rolloutBody,
);

console.log(JSON.stringify({
  ok: true,
  checks: [
    "long-running monitor owns latest-monitor-job.json",
    "once jobs do not overwrite long-running monitor state",
    "dry-run jobs do not overwrite live monitor state",
    "once dry-run jobs have a distinct diagnostic state file",
    "git mirror sync is a manual devops-infra Job, not a CronJob",
    "git mirror flush is a manual devops-infra Job, not a CronJob",
    "trigger-current can decide whether v0.2 git mirror pre-sync is required",
    "git mirror status exposes source and gitops GitHub sync state plus controlled flush command",
    "v0.2 control-plane status help exposes targeted PipelineRun/source-commit inspection",
    "v0.2 control-plane render uses a detached temp worktree from a CI/CD dedicated bare repo",
    "v0.2 status alignment reports stale-success without coupling CI to dirty workspace state",
    "v0.2 PipelineRun service matrix excludes hwlab-cli",
    "v0.2 false-green guard checks build TaskRuns, runtime artifact source commits, and reuse provenance",
    "v0.2 status warns on slow build TaskRuns",
    "rollout brief includes natural-language changelog before automatic diff summary",
    "semantic changelog extracts Chinese summary sections",
    "rollout brief includes lazy-build reused/rebuild metrics and service durations",
  ],
}, null, 2));
