#!/bin/bash
#
# tools/build-installer — build the x86_64 stock-OS installer bundle (ADR-0017,
# Session C). The installer/image analogue of a per-board .img.xz: a single
# tarball an operator unpacks on a stock Debian/Ubuntu x86_64 base and runs to
# get a Vendora server.
#
# Produces (per-platform artifact tag — ADR-0017 Decision #7):
#   vendora-sbc_<version>_x86_64_installer.tar.gz   (+ .sha256, + .manifest.txt)
#
# Bundle contents:
#   install-on-stock-os.sh            ← packaging/installer/
#   vendora-sbc_<version>_all.deb      ← built here (or --deb PATH)
#   license.env                        ← baked from .env.image if present (0600)
#   VERSION
#   packaging/                         ← lib + configs + keys + apt sources
#
# Runs on the build host (vendora-build). The .deb is Architecture: all, so no
# device + no cross-compile is needed.
#
# Usage:
#   tools/build-installer [--deb PATH] [--env-image PATH]
#
#   --deb PATH         use an existing .deb instead of building one
#   --env-image PATH   license keys to bake (default:
#                      image/armbian-build-config/.env.image if present)
# Output dir override:  INSTALLER_OUTPUT_DIR=<path> tools/build-installer

set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)"
OUTPUT_DIR="${INSTALLER_OUTPUT_DIR:-$HOME/armbian-build/output/installer}"

DEB_PATH=""
ENV_IMAGE="$PROJECT_ROOT/image/armbian-build-config/.env.image"

log() { echo "[vendora-build-installer] $*"; }
die() { echo "[vendora-build-installer] ERROR: $*" >&2; exit 1; }

while [ $# -gt 0 ]; do
    case "$1" in
        --deb)        DEB_PATH="${2:-}"; shift 2 ;;
        --env-image)  ENV_IMAGE="${2:-}"; shift 2 ;;
        -h|--help)    sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *) die "unknown option: $1" ;;
    esac
done

command -v dpkg-deb >/dev/null || die "dpkg-deb not found"
command -v rsync    >/dev/null || die "rsync not found"

# ---------------------------------------------------------------------------
# Version (single source of truth — same as the .deb + image).
# ---------------------------------------------------------------------------
VERSION="$(sed -n 's/^SBC_VERSION[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' \
    "$PROJECT_ROOT/services/common/version.py" | head -1)"
[ -n "$VERSION" ] || die "could not read SBC_VERSION from version.py"
log "version: $VERSION"

# ---------------------------------------------------------------------------
# The .deb — build it (Architecture: all, no device) unless one was passed.
# ---------------------------------------------------------------------------
if [ -z "$DEB_PATH" ]; then
    log "building the .deb via tools/build-deb"
    bash "$SCRIPT_DIR/build-deb"
    OUT="${DEB_OUTPUT_DIR:-$HOME/armbian-build/output/deb}"
    # Native (ADR-0021) builds the amd64 .deb on x86 hosts; fall back to the
    # legacy Architecture: all .deb if the operator ran build-deb --no-native.
    for CAND in "$OUT/vendora-sbc_${VERSION}_amd64.deb" "$OUT/vendora-sbc_${VERSION}_all.deb"; do
        [ -f "$CAND" ] && { DEB_PATH="$CAND"; break; }
    done
fi
[ -f "$DEB_PATH" ] || die "deb not found: $DEB_PATH"
log "using .deb: $DEB_PATH"

# ---------------------------------------------------------------------------
# Stage the bundle.
# ---------------------------------------------------------------------------
STAGING="$(mktemp -d -t vendora-installer-XXXXXX)"
trap 'rm -rf "$STAGING"' EXIT
BUNDLE="$STAGING/vendora-sbc_${VERSION}_x86_64_installer"
mkdir -p "$BUNDLE"

log "staging bundle at $BUNDLE"

# Installer script (LF + executable).
sed 's/\r$//' "$PROJECT_ROOT/packaging/installer/install-on-stock-os.sh" \
    > "$BUNDLE/install-on-stock-os.sh"
chmod 0755 "$BUNDLE/install-on-stock-os.sh"

# packaging/ — lib + configs + keys + apt sources (drop debian/ + systemd/:
# the .deb already carries the maintainer scripts + the units). Maintainer/
# shell text stays LF (matches the repo .gitattributes).
rsync -a \
    --exclude='debian' \
    --exclude='systemd' \
    --exclude='installer' \
    --exclude='README.md' \
    "$PROJECT_ROOT/packaging/" "$BUNDLE/packaging/"
# Normalize the shell lib + configs to LF (defensive against a CRLF checkout).
find "$BUNDLE/packaging" -type f \( -name '*.sh' -o -name '*.conf' -o -name '*.sources' \) \
    -exec sed -i 's/\r$//' {} +

# The package.
cp "$DEB_PATH" "$BUNDLE/"

# Version marker.
echo "$VERSION" > "$BUNDLE/VERSION"

# License keys — bake from .env.image (like the image), mode 0600. Optional:
# without it the server installs and reports "awaiting activation".
BAKED_LICENSE="no"
if [ -f "$ENV_IMAGE" ]; then
    api_key="$(sed -n 's/^VENDORA_API_KEY=//p' "$ENV_IMAGE" | head -1 | tr -d '\r')"
    signing_key="$(sed -n 's/^LICENSE_SIGNING_KEY=//p' "$ENV_IMAGE" | head -1 | tr -d '\r')"
    if [ -n "$api_key" ] && [ -n "$signing_key" ]; then
        printf 'VENDORA_API_KEY=%s\nLICENSE_SIGNING_KEY=%s\n' "$api_key" "$signing_key" \
            > "$BUNDLE/license.env"
        chmod 0600 "$BUNDLE/license.env"
        BAKED_LICENSE="yes"
        log "baked license.env (mode 0600) from $ENV_IMAGE"
    else
        log "WARN: $ENV_IMAGE present but keys empty — bundle ships without license.env"
    fi
else
    log "no .env.image — bundle ships without license.env (server will await activation)"
fi

# ---------------------------------------------------------------------------
# Tar it up.
# ---------------------------------------------------------------------------
mkdir -p "$OUTPUT_DIR"
TARBALL="$OUTPUT_DIR/vendora-sbc_${VERSION}_x86_64_installer.tar.gz"
log "creating $TARBALL"
tar -C "$STAGING" --owner=root --group=root -czf "$TARBALL" \
    "vendora-sbc_${VERSION}_x86_64_installer"

sha="$(sha256sum "$TARBALL" | awk '{print $1}')"
echo "$sha  $(basename "$TARBALL")" > "${TARBALL%.tar.gz}.sha256"
size="$(du -h "$TARBALL" | awk '{print $1}')"

# Self-extracting one-command installer (.run): a tiny stub with the bundle
# tarball base64-appended after a marker. The operator copies ONE file and runs
# ONE command — `sudo bash vendora-sbc_<ver>_x86_64.run [--harden]` — which
# unpacks to a temp dir and execs install-on-stock-os.sh, passing flags through.
RUN="$OUTPUT_DIR/vendora-sbc_${VERSION}_x86_64.run"
log "creating self-extracting $RUN"
cat > "$RUN" <<'STUB'
#!/bin/bash
# Vendora SBC — self-extracting x86_64 server installer.
#   sudo bash <this-file> [installer options]
# Unpacks the bundle to a temp dir and runs install-on-stock-os.sh. This release
# ALWAYS disables SSH (purges the server + sets a random root password).
set -euo pipefail
[ "$(id -u)" -eq 0 ] || { echo "run as root:  sudo bash $0 $*" >&2; exit 1; }
_tmp="$(mktemp -d)"; trap 'rm -rf "$_tmp"' EXIT
_start="$(awk '/^__VENDORA_INSTALLER_PAYLOAD__$/ {print NR+1; exit}' "$0")"
[ -n "$_start" ] || { echo "ERROR: payload marker missing" >&2; exit 1; }
tail -n +"$_start" "$0" | base64 -d | tar xz -C "$_tmp"
_dir="$(find "$_tmp" -maxdepth 1 -type d -name 'vendora-sbc_*_x86_64_installer' | head -1)"
[ -n "$_dir" ] || { echo "ERROR: bundle missing from payload" >&2; exit 1; }
exec bash "$_dir/install-on-stock-os.sh" --bundle-dir "$_dir" "$@"
__VENDORA_INSTALLER_PAYLOAD__
STUB
base64 -w0 "$TARBALL" >> "$RUN"
echo >> "$RUN"
chmod 0755 "$RUN"
run_sha="$(sha256sum "$RUN" | awk '{print $1}')"
echo "$run_sha  $(basename "$RUN")" > "${RUN%.run}.run.sha256"
run_size="$(du -h "$RUN" | awk '{print $1}')"

# Confidential manifest if it carries license keys.
MANIFEST="${TARBALL%.tar.gz}.manifest.txt"
{
    echo "Vendora SBC x86_64 installer manifest"
    echo "Built:        $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo "Version:      $VERSION"
    echo "Bundle:       $(basename "$TARBALL")"
    echo "SHA-256:      $sha"
    echo "Self-extract: $(basename "$RUN")"
    echo "  SHA-256:    $run_sha"
    echo "Package:      $(basename "$DEB_PATH")"
    echo "License keys: $BAKED_LICENSE (baked into bundle license.env)"
    if [ "$BAKED_LICENSE" = "yes" ]; then
        echo ""
        echo ">> CONFIDENTIAL: this bundle contains license.env. Treat like the image manifest."
    fi
} > "$MANIFEST"
chmod 600 "$MANIFEST"

log ""
log "DONE."
log "  one-file:  $RUN ($run_size)"
log "  bundle:    $TARBALL ($size)"
log "  manifest:  $MANIFEST"
log ""
log "Install on a stock Debian/Ubuntu x86_64 box — SIMPLE (one file, one command):"
log "  sudo bash $(basename "$RUN")              # SSH is always disabled (production)"
log ""
log "  (or the unpacked bundle:)"
log "  tar xzf $(basename "$TARBALL") && cd vendora-sbc_${VERSION}_x86_64_installer"
log "  sudo ./install-on-stock-os.sh             # SSH is always disabled (production)"
