#!/usr/bin/env bash
#
# build-image.sh — build the Alloy bootc image and a bootable artifact
# (installer ISO by default) with bootc-image-builder.
#
# Alloy re-brands os-release (ID=alloy, VERSION_ID=0.0). Two consequences
# are handled in the Containerfile (pinned $releasever, disabled build-only
# repos) and one here: bootc-image-builder has no distro definition named
# "alloy-0.0", so build/alloy-0.0.yaml is bind-mounted into its defs dir.
#
# Everything runs rootful on purpose: the image build and bib share one
# container store, so bib finds the image at /var/lib/containers/storage
# without a rootless->rootful copy.
#
# Usage:
#   build/build-image.sh                     # build image + installer ISO
#   build/build-image.sh --type raw          # build image + raw disk image
#   build/build-image.sh --skip-build        # reuse the current image, just run bib
#   build/build-image.sh --write /dev/sdX    # also dd the artifact to a device
#
# Writing requires an explicit device path and an interactive confirmation.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
IMAGE="localhost/alloy:local"
BIB_IMAGE="quay.io/centos-bootc/bootc-image-builder:latest"
DEF="$REPO_ROOT/build/alloy-0.0.yaml"
OUTPUT="$REPO_ROOT/output"

TYPE="iso"
WRITE_DEV=""
SKIP_BUILD=0

die() { printf 'error: %s\n' "$*" >&2; exit 1; }

usage() {
  sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
  exit "${1:-0}"
}

while [ $# -gt 0 ]; do
  case "$1" in
    --type)       TYPE="${2:?--type needs a value}"; shift 2 ;;
    --write)      WRITE_DEV="${2:?--write needs a device path}"; shift 2 ;;
    --skip-build) SKIP_BUILD=1; shift ;;
    -h|--help)    usage 0 ;;
    *)            die "unknown argument: $1 (see --help)" ;;
  esac
done

command -v podman >/dev/null || die "podman not found"
[ -f "$DEF" ] || die "missing distro def: $DEF"
[ -f "$REPO_ROOT/Containerfile" ] || die "no Containerfile at $REPO_ROOT"

# 1. Build the bootc image (rootful, so bib sees it in the same store).
if [ "$SKIP_BUILD" -eq 0 ]; then
  echo "==> Building $IMAGE (rootful)"
  sudo podman build -t "$IMAGE" "$REPO_ROOT"
else
  echo "==> Skipping image build; reusing $IMAGE"
  sudo podman image exists "$IMAGE" || die "$IMAGE not in the root store; drop --skip-build"
fi

# 2. Make sure the image builder is present.
sudo podman image exists "$BIB_IMAGE" || {
  echo "==> Pulling $BIB_IMAGE"
  sudo podman pull "$BIB_IMAGE"
}

# 3. Build the artifact. The alloy-0.0 def is mounted read-only into bib's
#    defs directory; librepo (the default) resolves repos from the image.
echo "==> Building --type $TYPE into $OUTPUT"
mkdir -p "$OUTPUT"
sudo rm -rf "${OUTPUT:?}/"* 2>/dev/null || true
sudo podman run --rm --privileged \
  --security-opt label=type:unconfined_t \
  -v /var/lib/containers/storage:/var/lib/containers/storage \
  -v "$OUTPUT":/output \
  -v "$DEF":/usr/share/bootc-image-builder/defs/alloy-0.0.yaml:ro \
  "$BIB_IMAGE" \
  --type "$TYPE" \
  --log-level info \
  "$IMAGE"

# 4. Locate the produced artifact.
case "$TYPE" in
  iso)          ARTIFACT="$OUTPUT/bootiso/install.iso" ;;
  raw)          ARTIFACT="$OUTPUT/image/disk.raw" ;;
  qcow2)        ARTIFACT="$OUTPUT/qcow2/disk.qcow2" ;;
  *)            ARTIFACT="$(sudo find "$OUTPUT" -type f ! -name '*.json' | head -1)" ;;
esac
[ -n "$ARTIFACT" ] && sudo test -f "$ARTIFACT" || die "expected artifact not found for type $TYPE"
echo "==> Built: $ARTIFACT ($(sudo du -h "$ARTIFACT" | cut -f1))"

# 5. Optionally write to a device.
if [ -n "$WRITE_DEV" ]; then
  [ -b "$WRITE_DEV" ] || die "$WRITE_DEV is not a block device"
  # Refuse to write to a disk that carries a mounted filesystem (root disk guard).
  if lsblk -nro MOUNTPOINT "$WRITE_DEV" | grep -qE '^/$|^/boot'; then
    die "$WRITE_DEV has a system mountpoint; refusing to write"
  fi
  echo
  lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL,SERIAL,TRAN "$WRITE_DEV"
  echo
  printf 'This ERASES all data on %s. Type the device path to confirm: ' "$WRITE_DEV"
  read -r reply
  [ "$reply" = "$WRITE_DEV" ] || die "confirmation did not match; not writing"
  echo "==> Writing $ARTIFACT to $WRITE_DEV"
  sudo dd if="$ARTIFACT" of="$WRITE_DEV" bs=4M oflag=direct conv=fsync status=progress
  sync
  echo "==> Done. $WRITE_DEV is now a bootable Alloy $TYPE."
else
  echo "==> To write it to a USB stick:"
  echo "    sudo dd if=$ARTIFACT of=/dev/sdX bs=4M oflag=direct conv=fsync status=progress"
  echo "    (or re-run with --write /dev/sdX to rebuild and write in one step)"
fi
