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

const roots: string[] = [];
const script = resolve(import.meta.dir, "runtime-gitops-postprocess.mjs");

afterEach(() => {
  while (roots.length > 0) rmSync(roots.pop()!, { recursive: true, force: true });
});

test("patches YAML-owned Code Agent and Kafka runtime settings", () => {
  const root = mkdtempSync(join(tmpdir(), "runtime-gitops-postprocess-"));
  roots.push(root);
  const runtimeDir = join(root, "runtime");
  mkdirSync(runtimeDir);
  writeFileSync(join(root, "overlay.json"), JSON.stringify(overlay("runtime")));
  writeFileSync(join(runtimeDir, "cloud-api.yaml"), deploymentYaml("hwlab-cloud-api"));
  writeFileSync(join(runtimeDir, "cloud-web.yaml"), `apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: unchanged\n---\n${deploymentYaml("hwlab-cloud-web")}`);
  writeFileSync(join(runtimeDir, "list.yaml"), `apiVersion: v1\nkind: List\nitems:\n${listItem(deploymentYaml("hwlab-cloud-api"))}\n`);
  writeFileSync(join(runtimeDir, "json-workload.yaml"), `${JSON.stringify(Bun.YAML.parse(deploymentYaml("hwlab-cloud-api")), null, 2)}\n`);

  const result = spawnSync(process.execPath, [script], {
    cwd: root,
    env: { ...process.env, UNIDESK_RUNTIME_GITOPS_OVERLAY_FILE: join(root, "overlay.json") },
    encoding: "utf8",
  });

  if (result.status !== 0) throw new Error(result.stderr);
  expect(result.stderr).toContain('"codeAgentRuntimeChanged":true');

  const api = Bun.YAML.parse(readFileSync(join(runtimeDir, "cloud-api.yaml"), "utf8")) as any;
  expect(envValues(api)).toMatchObject({
    HWLAB_CODE_AGENT_ADAPTER: "agentrun-v02",
    AGENTRUN_MGR_URL: "http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080",
    HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE: "agentrun-v02",
    HWLAB_CODE_AGENT_AGENTRUN_SECRET_NAMESPACE: "agentrun-v02",
    HWLAB_CODE_AGENT_AGENTRUN_GITHUB_TOOL_SECRET_NAME: "agentrun-v02-tool-github-pr",
    HWLAB_CODE_AGENT_AGENTRUN_UNIDESK_SSH_TOOL_SECRET_NAME: "agentrun-v02-tool-unidesk-ssh",
    HWLAB_KAFKA_ENABLED: "true",
    HWLAB_KAFKA_AGENTRUN_EVENT_CONSUME_ENABLED: "true",
    HWLAB_KAFKA_BOOTSTRAP_SERVERS: "kafka.platform-infra.svc.cluster.local:9092",
    HWLAB_KAFKA_STDIO_TOPIC: "agentrun.stdio.v1",
    HWLAB_KAFKA_AGENTRUN_EVENT_TOPIC: "agentrun.event.v1",
    HWLAB_KAFKA_EVENT_TOPIC: "hwlab.event.v1",
    HWLAB_KAFKA_CLIENT_ID: "hwlab-v03",
    HWLAB_KAFKA_DIRECT_PUBLISH_ENABLED: "true",
    HWLAB_KAFKA_TRANSACTIONAL_PROJECTOR_ENABLED: "false",
    HWLAB_KAFKA_PROJECTOR_GROUP_ID: "hwlab-projector",
    HWLAB_KAFKA_HWLAB_EVENT_GROUP_ID: "hwlab-events",
  });
  expect(envSecret(api, "AGENTRUN_API_KEY")).toEqual({ name: "hwlab-v03-master-server-admin-api-key", key: "api-key" });

  const multiDocs = readFileSync(join(runtimeDir, "cloud-web.yaml"), "utf8").split(/^---$/mu).map((document) => Bun.YAML.parse(document) as any);
  expect(multiDocs[0].kind).toBe("ConfigMap");
  expect(envValues(multiDocs[1])).toMatchObject({
    HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_ENABLED: "true",
    HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false",
  });

  const list = Bun.YAML.parse(readFileSync(join(runtimeDir, "list.yaml"), "utf8")) as any;
  expect(list.kind).toBe("List");
  expect(envValues(list.items[0]).AGENTRUN_MGR_URL).toBe("http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080");

  const jsonText = readFileSync(join(runtimeDir, "json-workload.yaml"), "utf8");
  expect(jsonText.startsWith("{\n")).toBe(true);
  expect(envValues(JSON.parse(jsonText)).HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE).toBe("agentrun-v02");

  const afterFirstRun = snapshot(runtimeDir);
  const second = spawnSync(process.execPath, [script], {
    cwd: root,
    env: { ...process.env, UNIDESK_RUNTIME_GITOPS_OVERLAY_FILE: join(root, "overlay.json") },
    encoding: "utf8",
  });
  if (second.status !== 0) throw new Error(second.stderr);
  expect(second.stderr).toContain('"codeAgentRuntimeChanged":false');
  expect(snapshot(runtimeDir)).toEqual(afterFirstRun);
});

function overlay(runtimePath: string) {
  return {
    runtimePath,
    codeAgentRuntime: {
      enabled: true,
      adapter: "agentrun-v02",
      managerUrl: "http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080",
      apiKeySecretName: "hwlab-v03-master-server-admin-api-key",
      apiKeySecretKey: "api-key",
      runnerNamespace: "agentrun-v02",
      secretNamespace: "agentrun-v02",
      toolSecretNames: {
        githubPr: "agentrun-v02-tool-github-pr",
        unideskSsh: "agentrun-v02-tool-unidesk-ssh",
      },
      defaultProviderProfile: "gpt.pika",
      codexStdioSupervisor: "repo-owned",
      kafkaEventBridge: {
        enabled: true,
        bootstrapServers: "kafka.platform-infra.svc.cluster.local:9092",
        stdioTopic: "agentrun.stdio.v1",
        agentRunEventTopic: "agentrun.event.v1",
        hwlabEventTopic: "hwlab.event.v1",
        clientId: "hwlab-v03",
        features: {
          directPublish: true,
          liveKafkaSse: true,
          kafkaRefreshReplay: true,
          transactionalProjector: false,
          projectionOutboxRelay: false,
          projectionRealtime: false,
        },
        directPublishConsumerGroupId: "hwlab-direct",
        transactionalProjectorConsumerGroupId: "hwlab-projector",
        hwlabEventConsumerGroupId: "hwlab-events",
        refreshReplay: {
          groupIdPrefix: "hwlab-refresh",
          timeoutMs: 30000,
          scanLimit: 1000,
          matchedEventLimit: 100,
          liveBufferLimit: 100,
        },
      },
    },
  };
}

function deploymentYaml(name: string) {
  return `apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: ${name}\n  labels:\n    app.kubernetes.io/name: ${name}\nspec:\n  template:\n    spec:\n      containers:\n        - name: ${name}\n          env:\n            - name: EXISTING\n              value: preserved\n`;
}

function listItem(value: string) {
  const [first, ...rest] = value.trimEnd().split("\n");
  return [`  - ${first}`, ...rest.map((line) => `    ${line}`)].join("\n");
}

function envValues(workload: any) {
  return Object.fromEntries(workload.spec.template.spec.containers[0].env.map((item: any) => [item.name, item.value]));
}

function envSecret(workload: any, name: string) {
  return workload.spec.template.spec.containers[0].env.find((item: any) => item.name === name)?.valueFrom?.secretKeyRef;
}

function snapshot(runtimeDir: string) {
  return ["cloud-api.yaml", "cloud-web.yaml", "list.yaml", "json-workload.yaml"].map((name) => readFileSync(join(runtimeDir, name), "utf8"));
}
