#!/usr/bin/env bash
# build-iso.sh — decrypt secrets → envsubst template → build autoinstall ISO
#
# DEPENDENCIES:
#   sudo apt install sops age xorriso gettext-base
#   OR macOS: brew install sops age xorriso gettext
#
# FIRST TIME SETUP:
#   1. age-keygen -o ~/.config/sops/age/keys.txt
#   2. Paste the public key (age1...) into .sops.yaml
#   3. Fill in secrets.yaml, then encrypt:
#        sops -e secrets.yaml > secrets.sops.yaml && rm secrets.yaml
#   4. git add .sops.yaml secrets.sops.yaml user-data.tmpl build-iso.sh .gitignore scripts/
#
# USAGE:
#   ./build-iso.sh
#   ./build-iso.sh --ubuntu-iso ~/Downloads/ubuntu-24.04.4-live-server-amd64.iso

set -euo pipefail

UBUNTU_ISO="${UBUNTU_ISO:-}"
UBUNTU_VERSION="24.04.4"
UBUNTU_ISO_URL="https://releases.ubuntu.com/${UBUNTU_VERSION}/ubuntu-${UBUNTU_VERSION}-live-server-amd64.iso"
WORK_DIR="$(mktemp -d /tmp/autoinstall-build.XXXXXX)"
OUTPUT_ISO="autoinstall-$(date +%Y%m%d-%H%M).iso"
SOPS_FILE="secrets.sops.yaml"
TEMPLATE_DIR="templates"
TARGET_USER=$(yq -r .autoinstall.identity.username templates/user-data.tmpl)
export TARGET_USER
NOCLOUD_DIR="$WORK_DIR/iso/nocloud"
mkdir -p "$NOCLOUD_DIR"

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
info() { echo -e "${GREEN}[+]${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
error() {
  echo -e "${RED}[✗]${NC} $*"
  exit 1
}
function envsubst_in_place() {
  set -x
  local _filename=$1
  envsubst "\$TARGET_USER" <"$_filename" >$_filename.tmp && mv $_filename.tmp $_filename
  set +x
}

while [[ $# -gt 0 ]]; do
  case $1 in
  --ubuntu-iso)
    UBUNTU_ISO="$2"
    shift 2
    ;;
  *) error "Unknown argument: $1" ;;
  esac
done

cleanup() {
  info "Cleaning up..."
  echo "$WORK_DIR"
  rm -rf "$WORK_DIR"
}
trap cleanup EXIT

for cmd in sops envsubst xorriso; do
  command -v "$cmd" &>/dev/null || error "'$cmd' not found. Install it first."
done

export SOPS_AGE_KEY_FILE="${SOPS_AGE_KEY_FILE:-$HOME/.config/sops/age/keys.txt}"
[[ -f "$SOPS_AGE_KEY_FILE" ]] || error "age key not found at $SOPS_AGE_KEY_FILE"

# ── Decrypt secrets → render template ─────────────────────────────────────────
info "Decrypting secrets and rendering template..."
sops exec-env "$SOPS_FILE" "envsubst < $TEMPLATE_DIR/user-data.tmpl > $NOCLOUD_DIR/user-data"
sops exec-env "$SOPS_FILE" "envsubst '\$WIFI_HOUSE_PASSWORD \$NOKIA_WIFI_KEY_PASSWORD' < $TEMPLATE_DIR/user-data-wifi.tmpl > $NOCLOUD_DIR/user-data-wifi.config"

envsubst_in_place "$NOCLOUD_DIR/user-data"
envsubst_in_place "$NOCLOUD_DIR/user-data-wifi.config"

info "Template rendered."

# ── Get Ubuntu ISO ─────────────────────────────────────────────────────────────
if [[ -n "$UBUNTU_ISO" ]]; then
  [[ -f "$UBUNTU_ISO" ]] || error "ISO not found: $UBUNTU_ISO"
  info "Using provided ISO: $UBUNTU_ISO"
else
  UBUNTU_ISO="ubuntu-${UBUNTU_VERSION}-live-server-amd64.iso"
  if [[ ! -f "$UBUNTU_ISO" ]]; then
    info "Downloading Ubuntu ${UBUNTU_VERSION} server ISO..."
    curl -L --fail --progress-bar -o "$UBUNTU_ISO" "$UBUNTU_ISO_URL" ||
      {
        rm -f "$UBUNTU_ISO"
        error "Download failed (check URL or network): $UBUNTU_ISO_URL"
      }
  else
    info "Found cached ISO: $UBUNTU_ISO"
  fi
fi

# ── Extract ISO ────────────────────────────────────────────────────────────────
info "Extracting ISO..."
xorriso -osirrox on -indev "$UBUNTU_ISO" -extract / "$WORK_DIR/iso" 2>/dev/null
chmod -R u+w "$WORK_DIR/iso"

# Extract MBR template directly from the original ISO (first 432 bytes)
# boot_hybrid.img is NOT present in the extracted filesystem on 24.04
dd if="$UBUNTU_ISO" bs=1 count=432 of="$WORK_DIR/mbr_template.bin" 2>/dev/null

# ── Inject autoinstall files ───────────────────────────────────────────────────
info "Injecting autoinstall config and post-install script..."

cp deployment/* "$NOCLOUD_DIR/"
touch "$NOCLOUD_DIR/meta-data"

envsubst_in_place "$NOCLOUD_DIR/post-install.sh"

cp -r $NOCLOUD_DIR /tmp/

# ── Patch GRUB ────────────────────────────────────────────────────────────────
GRUB_CFG="$WORK_DIR/iso/boot/grub/grub.cfg"
if [[ -f "$GRUB_CFG" ]]; then
  info "Patching GRUB for unattended boot..."
  cat >"$WORK_DIR/grub_prepend.cfg" <<'GRUBENTRY'
set default=0
set timeout=1

menuentry "Autoinstall Ubuntu" {
    set gfxpayload=keep
    linux /casper/vmlinuz quiet autoinstall ds=nocloud\;s=/cdrom/nocloud/ ---
    initrd /casper/initrd
}

GRUBENTRY
  # Prepend our entry, then append the original (so manual install is still reachable)
  cat "$WORK_DIR/grub_prepend.cfg" "$GRUB_CFG" >"$WORK_DIR/grub_merged.cfg"
  mv "$WORK_DIR/grub_merged.cfg" "$GRUB_CFG"
fi

EFI_LINE=$(fdisk -l "$UBUNTU_ISO" | grep "EFI System")
EFI_START=$(echo "$EFI_LINE" | awk '{print $(NF-5)}')
EFI_END=$(echo "$EFI_LINE" | awk '{print $(NF-4)}')
EFI_COUNT=$((EFI_END - EFI_START + 1))

# ── Repack ISO ─────────────────────────────────────────────────────────────────
xorriso -as mkisofs \
  -r -V "Ubuntu-AutoInstall" -o "$OUTPUT_ISO" \
  -J -joliet-long \
  --grub2-mbr --interval:local_fs:0s-15s:zero_mbrpt,zero_gpt:"$UBUNTU_ISO" \
  --protective-msdos-label \
  -partition_offset 16 \
  --mbr-force-bootable \
  -append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b \
  --interval:local_fs:${EFI_START}d-${EFI_END}d::"$UBUNTU_ISO" \
  -appended_part_as_gpt \
  -iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
  -c '/boot.catalog' \
  -b '/boot/grub/i386-pc/eltorito.img' \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  --grub2-boot-info \
  -eltorito-alt-boot \
  -e "--interval:appended_partition_2_start_${EFI_START}s_size_${EFI_COUNT}d:all::" \
  -no-emul-boot \
  -boot-load-size $EFI_COUNT \
  "$WORK_DIR/iso"

info "Done! ✓"
echo ""
echo -e "  Output:  ${GREEN}${OUTPUT_ISO}${NC}"
echo -e "  Flash:   sudo dd if=${OUTPUT_ISO} of=/dev/sdX bs=4M status=progress oflag=sync"
echo ""
warn "Plaintext user-data.yaml deleted. secrets.yaml never hit disk."
