#!/usr/bin/env node
// Responsibility: apply the YAML-owned HWLAB Pipeline provenance contract during the normal control-plane postprocess.
import { readFileSync, writeFileSync } from "node:fs";
import { createRequire } from "node:module";

const require = createRequire(`${process.cwd()}/package.json`);
const YAML = require("yaml");

export function applyHwlabPipelineProvenance(manifest, annotations, expectedKeys) {
  if (!isRecord(manifest) || manifest.kind !== "Pipeline") return false;
  const entries = isRecord(annotations) ? Object.entries(annotations) : [];
  const actualKeys = entries.map(([key]) => key).sort();
  const sortedExpectedKeys = Array.isArray(expectedKeys) ? [...expectedKeys].sort() : [];
  if (JSON.stringify(actualKeys) !== JSON.stringify(sortedExpectedKeys) || entries.some(([, value]) => typeof value !== "string" || value.length === 0)) {
    throw new Error("overlay.pipelineProvenanceAnnotations must match the shared four-key contract");
  }
  manifest.metadata = isRecord(manifest.metadata) ? manifest.metadata : {};
  manifest.metadata.annotations = { ...(isRecord(manifest.metadata.annotations) ? manifest.metadata.annotations : {}), ...annotations };
  return true;
}

export function postprocessHwlabPipelineProvenance({ pipelinePath, overlay, expectedKeys }) {
  const documents = YAML.parseAllDocuments(readFileSync(pipelinePath, "utf8"));
  const manifests = documents.map((document) => document.toJS()).filter((document) => document !== null);
  const changed = manifests.filter((manifest) => applyHwlabPipelineProvenance(manifest, overlay.pipelineProvenanceAnnotations, expectedKeys));
  if (changed.length !== 1) throw new Error(`expected exactly one Pipeline in ${pipelinePath}; observed ${changed.length}`);
  writeFileSync(pipelinePath, `${manifests.map((manifest) => YAML.stringify(manifest).trimEnd()).join("\n---\n")}\n`);
  return { pipelinePath, pipelineName: changed[0]?.metadata?.name ?? null, annotationCount: expectedKeys.length };
}

function isRecord(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

function requiredArgument(name) {
  const index = process.argv.indexOf(name);
  const value = index === -1 ? undefined : process.argv[index + 1];
  if (typeof value !== "string" || value.length === 0 || value.startsWith("--")) throw new Error(`${name} is required`);
  return value;
}

function decodedJsonEnv(name) {
  const encoded = process.env[name];
  if (typeof encoded !== "string" || encoded.length === 0) throw new Error(`${name} is required`);
  return JSON.parse(Buffer.from(encoded, "base64").toString("utf8"));
}

if (process.argv.includes("--pipeline")) {
  const result = postprocessHwlabPipelineProvenance({
    pipelinePath: requiredArgument("--pipeline"),
    overlay: decodedJsonEnv("UNIDESK_RUNTIME_GITOPS_OVERLAY_B64"),
    expectedKeys: decodedJsonEnv("UNIDESK_PIPELINE_PROVENANCE_KEYS_B64"),
  });
  console.error(JSON.stringify({ event: "unidesk-runtime-pipeline-provenance", ok: true, ...result }));
}
