import { expect, test } from "bun:test";
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { spawnSync } from "node:child_process";

import { resolveAgentRunLaneTarget } from "./agentrun-lanes";
import { renderAgentRunPipelineManifest } from "./agentrun-manifests";
import { renderPacFeatureConfigSchemaStage } from "./pac-feature-config-schema-stage";

test("shared stage injects owning YAML OTel values for all three PaC repositories", () => {
  for (const [repositoryId, consumer] of [
    ["hwlab-nc01-v03", "hwlab-nc01-v03"],
    ["agentrun-nc01-v02", "agentrun-nc01-v02"],
    ["sentinel-nc01-v03", "sentinel-nc01-v03"],
  ] as const) {
    const stage = renderPacFeatureConfigSchemaStage({
      repositoryId,
      consumer,
      repoDirExpression: "'/workspace/source'",
      renderedRootExpression: "'/workspace/rendered'",
    });
    expect(stage).toContain("feature-config-schema-validation");
    expect(stage).toContain("cicd.feature_config.schema");
    expect(stage).toContain("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT='http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces'");
    expect(stage).toContain("OTEL_TRACES_SAMPLER_ARG='1'");
    expect(stage).toContain("OTEL_EXPORTER_TIMEOUT_MS='300'");
    expect(stage).not.toContain("process.env.webProbeSentinel");
  }
});

test("embedded node process failure remains a typed warning with zero shell exit", () => {
  const root = mkdtempSync(join(tmpdir(), "feature-config-stage-"));
  try {
    const bin = join(root, "bin");
    mkdirSync(bin);
    writeFileSync(join(bin, "node"), "#!/bin/sh\nexit 71\n", { mode: 0o755 });
    const stage = renderPacFeatureConfigSchemaStage({
      repositoryId: "sentinel-nc01-v03",
      consumer: "sentinel-nc01-v03",
      repoDirExpression: "'/workspace/source'",
      renderedRootExpression: "'/workspace/rendered'",
    });
    const result = spawnSync("sh", [], {
      input: `set -eu\n${stage}\n`,
      env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}` },
      encoding: "utf8",
    });
    expect(result.status).toBe(0);
    expect(result.stderr).toContain("feature-config-validator-process-failure");
  } finally {
    rmSync(root, { recursive: true, force: true });
  }
});

test("AgentRun normal GitOps publish task contains the shared warning-only stage", () => {
  const { spec } = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" });
  const pipeline = renderAgentRunPipelineManifest(spec) as Record<string, any>;
  const scripts = pipeline.spec.tasks.flatMap((task: Record<string, any>) => task.taskSpec.steps.map((step: Record<string, any>) => String(step.script ?? ""))).join("\n");
  expect(scripts).toContain("UNIDESK_PAC_CONSUMER='agentrun-nc01-v02'");
  expect(scripts).toContain("feature-config-schema-validation");
  expect(scripts).toContain("feature-config-validator-process-failure");
  expect(scripts).toContain("OTEL_EXPORTER_TIMEOUT_MS='300'");
});

test("repo-owned schema is Draft 2020-12 with one canonical feature property", () => {
  const schema = JSON.parse(readFileSync("config/feature-config.schema.json", "utf8"));
  expect(schema.$schema).toBe("https://json-schema.org/draft/2020-12/schema");
  expect(schema.properties.webProbeSentinel["x-unidesk-feature"]).toBe("web-probe-sentinel");
  expect(Object.keys(schema.properties)).toEqual(["webProbeSentinel"]);
});
