#!/bin/bash
# Generate Image Digest Lock File
# Collects currently running images and resolves immutable digests per host

set -euo pipefail

usage() {
  cat << EOF
Generate Image Digest Lock File

Usage:
  $0 --hosts "omv800 surface fedora" --output /opt/migration/configs/image-digest-lock.yaml

Options:
  --hosts   Space-separated hostnames to query over SSH (required)
  --output  Output lock file path (default: ./image-digest-lock.yaml)
  --help    Show this help

Notes:
  - Requires passwordless SSH or ssh-agent for each host
  - Each host must have Docker CLI and network access to resolve digests
  - Falls back to remote `docker image inspect` to fetch RepoDigests
EOF
}

HOSTS=""
OUTPUT="./image-digest-lock.yaml"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --hosts)
      HOSTS="$2"; shift 2 ;;
    --output)
      OUTPUT="$2"; shift 2 ;;
    --help|-h)
      usage; exit 0 ;;
    *)
      echo "Unknown argument: $1" >&2; usage; exit 1 ;;
  esac
done

if [[ -z "$HOSTS" ]]; then
  echo "--hosts is required" >&2
  usage
  exit 1
fi

TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT

echo "# Image Digest Lock" > "$OUTPUT"
echo "# Generated: $(date -Iseconds)" >> "$OUTPUT"
echo "hosts:" >> "$OUTPUT"

for HOST in $HOSTS; do
  echo "  $HOST:" >> "$OUTPUT"

  # Get running images (name:tag or id)
  IMAGES=$(ssh -o ConnectTimeout=10 "$HOST" "docker ps --format '{{.Image}}'" 2>/dev/null || true)
  if [[ -z "$IMAGES" ]]; then
    echo "    images: []" >> "$OUTPUT"
    continue
  fi

  echo "    images:" >> "$OUTPUT"

  while IFS= read -r IMG; do
    [[ -z "$IMG" ]] && continue

    # Inspect to get RepoDigests (immutable digests)
    INSPECT_JSON=$(ssh "$HOST" "docker image inspect '$IMG'" 2>/dev/null || true)
    if [[ -z "$INSPECT_JSON" ]]; then
      # Try to pull metadata silently to populate digest cache (without actual layer download)
      ssh "$HOST" "docker pull --quiet '$IMG' > /dev/null 2>&1 || true"
      INSPECT_JSON=$(ssh "$HOST" "docker image inspect '$IMG'" 2>/dev/null || true)
    fi

    DIGEST_LINE=""
    if command -v jq >/dev/null 2>&1; then
      DIGEST_LINE=$(echo "$INSPECT_JSON" | jq -r '.[0].RepoDigests[0] // ""' 2>/dev/null || echo "")
    else
      # Grep/sed fallback: find first RepoDigests entry
      DIGEST_LINE=$(echo "$INSPECT_JSON" | grep -m1 'RepoDigests' -A2 | grep -m1 sha256 | sed 's/[", ]//g' || true)
    fi

    # If no digest, record unresolved entry
    if [[ -z "$DIGEST_LINE" || "$DIGEST_LINE" == "null" ]]; then
      echo "      - image: \"$IMG\"" >> "$OUTPUT"
      echo "        resolved: false" >> "$OUTPUT"
      continue
    fi

    # Split repo@sha digest
    IMAGE_AT_DIGEST="$DIGEST_LINE"

    # Try to capture the original tag (if present)
    ORIG_TAG="$IMG"

    echo "      - image: \"$ORIG_TAG\"" >> "$OUTPUT"
    echo "        digest: \"$IMAGE_AT_DIGEST\"" >> "$OUTPUT"
    echo "        resolved: true" >> "$OUTPUT"
  done <<< "$IMAGES"
done

echo "\nWrote lock file: $OUTPUT"


