#!/bin/sh
set -eu

payload_dir=$(mktemp -d)
cleanup() {
  status=$?
  trap - 0 1 2 15
  rm -rf "$payload_dir"
  exit "$status"
}
trap cleanup 0 1 2 15

UNIDESK_PAC_EVALUATOR_PATH="$payload_dir/pac-status-evaluator.cjs"
printf '%s' "$UNIDESK_PAC_EVALUATOR_B64" | base64 -d >"$UNIDESK_PAC_EVALUATOR_PATH"
export UNIDESK_PAC_EVALUATOR_PATH

read_errors="$payload_dir/read-errors.jsonl"
: >"$read_errors"

capture_list() {
  stage="$1"
  resource="$2"
  output="$3"
  selector="${4:-}"
  printf '{"event":"pac-node-snapshot-progress","stage":"%s","status":"started","valuesPrinted":false}\n' "$stage" >&2
  if [ -n "$selector" ]; then
    if timeout "$UNIDESK_PAC_READ_STEP_TIMEOUT_SECONDS" kubectl get "$resource" -A -l "$selector" -o json >"$output" 2>"$payload_dir/$stage.stderr"; then
      exit_code=0
    else
      exit_code=$?
    fi
  else
    if timeout "$UNIDESK_PAC_READ_STEP_TIMEOUT_SECONDS" kubectl get "$resource" -A -o json >"$output" 2>"$payload_dir/$stage.stderr"; then
      exit_code=0
    else
      exit_code=$?
    fi
  fi
  if [ "$exit_code" -eq 0 ]; then
    printf '{"event":"pac-node-snapshot-progress","stage":"%s","status":"completed","valuesPrinted":false}\n' "$stage" >&2
    return 0
  fi
  printf '{"event":"pac-node-snapshot-progress","stage":"%s","status":"failed","exitCode":%s,"valuesPrinted":false}\n' \
    "$stage" "$exit_code" >&2
  printf '{"stage":"%s","code":"pac-node-%s-read-failed","exitCode":%s,"valuesPrinted":false}\n' \
    "$stage" "$stage" "$exit_code" >>"$read_errors"
  printf '{"items":[]}' >"$output"
}

capture_pipeline_runs() {
  output="$1"
  selector="$2"
  namespace_dir="$payload_dir/pipeline-run-namespaces"
  mkdir -p "$namespace_dir"
  printf '{"event":"pac-node-snapshot-progress","stage":"pipeline-runs","status":"started","valuesPrinted":false}\n' >&2
  jobs=""
  for namespace in $UNIDESK_PAC_PIPELINERUN_NAMESPACES; do
    (
      timeout "$UNIDESK_PAC_READ_STEP_TIMEOUT_SECONDS" \
        kubectl -n "$namespace" get pipelinerun.tekton.dev -l "$selector" -o json \
        >"$namespace_dir/$namespace.json" 2>"$namespace_dir/$namespace.stderr"
    ) &
    jobs="$jobs $!:$namespace"
  done
  failed=false
  for job in $jobs; do
    pid="${job%%:*}"
    namespace="${job#*:}"
    if wait "$pid"; then
      :
    else
      exit_code=$?
      failed=true
      printf '{"stage":"pipeline-runs","namespace":"%s","code":"pac-node-pipeline-runs-read-failed","exitCode":%s,"valuesPrinted":false}\n' \
        "$namespace" "$exit_code" >>"$read_errors"
      printf '{"items":[]}' >"$namespace_dir/$namespace.json"
    fi
  done
  node - "$namespace_dir" >"$output" <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const directory = process.argv[2];
const items = fs.readdirSync(directory)
  .filter((name) => name.endsWith(".json"))
  .sort()
  .flatMap((name) => {
    try {
      const parsed = JSON.parse(fs.readFileSync(path.join(directory, name), "utf8"));
      return Array.isArray(parsed.items) ? parsed.items : [];
    } catch {
      return [];
    }
  });
process.stdout.write(JSON.stringify({ items }));
NODE
  if [ "$failed" = true ]; then
    printf '{"event":"pac-node-snapshot-progress","stage":"pipeline-runs","status":"failed","valuesPrinted":false}\n' >&2
  else
    printf '{"event":"pac-node-snapshot-progress","stage":"pipeline-runs","status":"completed","valuesPrinted":false}\n' >&2
  fi
}

capture_pipeline_runs "$payload_dir/pipelineruns.json" "$UNIDESK_PAC_PIPELINERUN_SELECTOR"
capture_list argo-applications application.argoproj.io "$payload_dir/applications.json"
capture_list deployments deployment.apps "$payload_dir/deployments.json"

node - "$payload_dir" <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const payloadDir = process.argv[2];
const readJson = (name, fallback) => {
  try { return JSON.parse(fs.readFileSync(path.join(payloadDir, name), "utf8") || JSON.stringify(fallback)); }
  catch { return fallback; }
};
const readErrors = fs.readFileSync(path.join(payloadDir, "read-errors.jsonl"), "utf8")
  .split(/\r?\n/u)
  .filter(Boolean)
  .map((line) => JSON.parse(line));
const consumers = JSON.parse(Buffer.from(process.env.UNIDESK_PAC_NODE_CONSUMERS_B64 || "W10=", "base64").toString("utf8"));
const { evaluatePacNodeStatusSnapshot } = require(process.env.UNIDESK_PAC_EVALUATOR_PATH);
const result = evaluatePacNodeStatusSnapshot({
  consumers,
  pipelineRuns: readJson("pipelineruns.json", { items: [] }),
  applications: readJson("applications.json", { items: [] }),
  deployments: readJson("deployments.json", { items: [] }),
  readErrors,
});
process.stdout.write(`${JSON.stringify(result)}\n`);
NODE
