#!/usr/bin/env bash
## pull-container-images.sh — refresh every active container_type's image.
##
## Iterates rows in whp.container_types where active=1, runs `docker pull`
## on each base_image, and logs per-image status + a summary tail.
##
## Invoked nightly by /etc/cron.d/whp-image-pull (installed by
## scripts/setup-image-pull-cron.sh). Also safe to run manually.
##
## Per-image pulls run sequentially to avoid hammering the registry
## (~25 images, ~1-2s each on cache-hit, ~5-30s on fresh layers).
set -euo pipefail

LOG=/var/log/whp-image-pull.log
LOCK=/run/whp-image-pull.lock

mkdir -p "$(dirname "$LOG")"

ts() { date '+%Y-%m-%d %H:%M:%S'; }
log() { echo "[$(ts)] $*" | tee -a "$LOG"; }

## Lock so two invocations (cron + manual) don't double-pull. flock -n
## means non-blocking — second invocation exits immediately.
exec 200>"$LOCK"
if ! flock -n 200; then
  log "another pull-container-images run is in progress, exiting"
  exit 0
fi

log "=== pull-container-images start ==="

if ! command -v mysql >/dev/null 2>&1; then
  log "FATAL: mysql client not found"
  exit 1
fi

## Pull the active image set. Filter by `active=1` so deprecated types
## (e.g. eol_date passed) don't waste bandwidth.
mapfile -t images < <(mysql -N -e "SELECT DISTINCT base_image FROM whp.container_types WHERE active = 1 ORDER BY base_image;")

if [ ${#images[@]} -eq 0 ]; then
  log "no active container_types found, nothing to pull"
  exit 0
fi

total=${#images[@]}
ok=0
updated=0
failed=0

log "found $total active image(s) to refresh"

for img in "${images[@]}"; do
  [ -z "$img" ] && continue
  log "pulling: $img"
  ## Capture both stdout and stderr; docker pull writes progress to stderr.
  ## Treat any line containing "Downloaded newer image" as an update signal.
  out=$(docker pull "$img" 2>&1)
  rc=$?
  if [ "$rc" -eq 0 ]; then
    ok=$((ok+1))
    if echo "$out" | grep -q "Downloaded newer image"; then
      updated=$((updated+1))
      log "  OK (updated): $img"
    else
      log "  OK (up to date): $img"
    fi
  else
    failed=$((failed+1))
    log "  FAIL: $img"
    echo "$out" | tail -5 | sed 's/^/    /' | tee -a "$LOG" >/dev/null
  fi
done

log "summary: $total checked, $updated updated, $((ok-updated)) already current, $failed failed"
log "=== pull-container-images done ==="

## Exit non-zero if any image failed — surfaces in cron failure handling
## but keeps logs intact for manual review.
if [ "$failed" -gt 0 ]; then
  exit 2
fi
