#!/usr/bin/env bash
# Update every Factory Kubernetes admission pin after GHCR returns a new digest.
set -euo pipefail

usage() {
  echo "usage: $0 sha256:<64 lowercase hex characters>" >&2
  exit 2
}

[[ $# -eq 1 ]] || usage
new_digest=$1
[[ $new_digest =~ ^sha256:[0-9a-f]{64}$ ]] || {
  echo "update-approved-image: invalid digest: $new_digest" >&2
  exit 2
}

script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
factory_dir=$(cd -- "$script_dir/.." && pwd)
approved_image_file="$factory_dir/adw_modules/kubernetes_job.py"
runtime_file="$script_dir/runtime.yaml"
tests_dir="$factory_dir/tests"
image_prefix='ghcr.io/alexcodeplace/overdeck-agent-sandbox@'

old_image=$(sed -nE 's/^APPROVED_IMAGE = "(ghcr\.io\/alexcodeplace\/overdeck-agent-sandbox@sha256:[0-9a-f]{64})"$/\1/p' "$approved_image_file")
if [[ ! $old_image =~ ^ghcr\.io/alexcodeplace/overdeck-agent-sandbox@sha256:[0-9a-f]{64}$ ]]; then
  echo "update-approved-image: could not read APPROVED_IMAGE from $approved_image_file" >&2
  exit 1
fi
new_image="$image_prefix$new_digest"

if [[ $old_image == "$new_image" ]]; then
  echo "update-approved-image: already pinned to $new_image"
  exit 0
fi

# Search fixtures as well: a literal fixture pin must move with the admission policy.
mapfile -t files < <(rg -l --fixed-strings -- "$old_image" "$approved_image_file" "$runtime_file" "$tests_dir")
for required in "$approved_image_file" "$runtime_file"; do
  if ! printf '%s\n' "${files[@]}" | grep -Fqx -- "$required"; then
    echo "update-approved-image: missing required pin site: $required" >&2
    exit 1
  fi
done

declare -a temporary_files=()
declare -a changed_lines=()
cleanup() {
  rm -f -- "${temporary_files[@]:-}"
}
trap cleanup EXIT

# Stage every replacement before changing a source file, then use same-directory
# renames so readers never observe a partly-written pin file.
for file in "${files[@]}"; do
  while IFS=: read -r path line _; do
    changed_lines+=("$path:$line")
  done < <(rg -n --with-filename --fixed-strings -- "$old_image" "$file")

  temporary=$(mktemp "${file}.update-approved-image.XXXXXX")
  temporary_files+=("$temporary")
  sed "s|$old_image|$new_image|g" "$file" >"$temporary"
  chmod --reference="$file" "$temporary"
done

for index in "${!files[@]}"; do
  mv -f -- "${temporary_files[$index]}" "${files[$index]}"
done
temporary_files=()

printf '%s\n' "${changed_lines[@]}"
