#!/usr/bin/env bash
# make-golden-bundle.sh
#
# Build the banger golden image from images/golden/Dockerfile and
# package it as a .tar.zst bundle suitable for publishing to the
# imagecat catalog. Does not upload — see publish-golden-image.sh.
#
# Pipeline:
#   docker build -> docker create -> docker export | banger internal make-bundle
#
# Usage:
#   scripts/make-golden-bundle.sh [--name <n>] [--kernel-ref <k>] \
#     [--distro <d>] [--arch <a>] [--description "..."] \
#     [--out <path>] [--size <spec>] [--platform <p>]
#
# Defaults:
#   --name         debian-bookworm
#   --kernel-ref   generic-6.12
#   --distro       debian
#   --arch         x86_64
#   --platform     linux/amd64
#   --out          <repo>/dist/<name>-<arch>.tar.zst
#
# Environment overrides:
#   BANGER_BIN                path to banger binary (default build/bin/banger)
#   BANGER_VSOCK_AGENT_BIN    path to companion (default build/bin/banger-vsock-agent)

set -euo pipefail

log() { printf '[make-golden-bundle] %s\n' "$*" >&2; }
die() { log "$*"; exit 1; }

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
DOCKERFILE="$REPO_ROOT/images/golden/Dockerfile"
CONTEXT="$REPO_ROOT/images/golden"

NAME="debian-bookworm"
KERNEL_REF="generic-6.12"
DISTRO="debian"
ARCH="x86_64"
DESCRIPTION=""
OUT=""
# 4G is a deliberate over-allocation for the golden image: it leaves
# room for first-boot apt-installs of sshd on derived pulls and for
# the user's own apt-installs during sandbox use.
SIZE="4G"
PLATFORM="linux/amd64"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --name) NAME="${2:-}"; shift 2;;
    --kernel-ref) KERNEL_REF="${2:-}"; shift 2;;
    --distro) DISTRO="${2:-}"; shift 2;;
    --arch) ARCH="${2:-}"; shift 2;;
    -d|--description) DESCRIPTION="${2:-}"; shift 2;;
    --out) OUT="${2:-}"; shift 2;;
    --size) SIZE="${2:-}"; shift 2;;
    --platform) PLATFORM="${2:-}"; shift 2;;
    -h|--help)
      sed -n '2,/^set -euo/p' "$0" | sed 's/^# \?//' | sed '$d'
      exit 0
      ;;
    *) die "unknown option: $1";;
  esac
done

for tool in docker zstd sha256sum; do
  command -v "$tool" >/dev/null 2>&1 || die "missing required tool: $tool"
done
[[ -f "$DOCKERFILE" ]] || die "dockerfile missing: $DOCKERFILE"

BANGER_BIN="${BANGER_BIN:-$REPO_ROOT/build/bin/banger}"
[[ -x "$BANGER_BIN" ]] || die "banger binary not executable: $BANGER_BIN (run 'make build' or set BANGER_BIN)"
VSOCK_AGENT="${BANGER_VSOCK_AGENT_BIN:-$REPO_ROOT/build/bin/banger-vsock-agent}"
[[ -x "$VSOCK_AGENT" ]] || die "banger-vsock-agent not executable: $VSOCK_AGENT (run 'make build')"

if [[ -z "$OUT" ]]; then
  OUT="$REPO_ROOT/dist/${NAME}-${ARCH}.tar.zst"
fi
mkdir -p "$(dirname "$OUT")"

DOCKER_TAG="banger-golden:${NAME}"

log "building $DOCKER_TAG (platform=$PLATFORM)"
docker build --platform "$PLATFORM" -t "$DOCKER_TAG" -f "$DOCKERFILE" "$CONTEXT"

log "creating docker container (not started)"
CONTAINER_ID="$(docker create "$DOCKER_TAG")"
cleanup() { docker rm -f "$CONTAINER_ID" >/dev/null 2>&1 || true; }
trap cleanup EXIT

log "piping container filesystem into banger internal make-bundle"
SIZE_FLAG=()
[[ -n "$SIZE" ]] && SIZE_FLAG=(--size "$SIZE")
DESC_FLAG=()
[[ -n "$DESCRIPTION" ]] && DESC_FLAG=(--description "$DESCRIPTION")
KERNEL_REF_FLAG=()
[[ -n "$KERNEL_REF" ]] && KERNEL_REF_FLAG=(--kernel-ref "$KERNEL_REF")

export BANGER_VSOCK_AGENT_BIN="$VSOCK_AGENT"
docker export "$CONTAINER_ID" | \
  "$BANGER_BIN" internal make-bundle \
    --rootfs-tar - \
    --name "$NAME" \
    --distro "$DISTRO" \
    --arch "$ARCH" \
    "${KERNEL_REF_FLAG[@]}" \
    "${DESC_FLAG[@]}" \
    "${SIZE_FLAG[@]}" \
    --out "$OUT"

SHA256="$(sha256sum "$OUT" | awk '{print $1}')"
SIZE_BYTES="$(stat -c '%s' "$OUT")"
HUMAN="$(numfmt --to=iec --suffix=B "$SIZE_BYTES" 2>/dev/null || echo "${SIZE_BYTES}B")"

log "bundle: $OUT"
log "sha256: $SHA256"
log "size:   $HUMAN ($SIZE_BYTES bytes)"
printf '%s\n' "$OUT"
