#!/usr/bin/env bash
# Deploy the metronome to the Caddy web root that serves
# https://metronome.varasys.io
#
# Caddy config: /var/lib/caddy/Caddyfile  (metronome.varasys.io:8443 block)
# Bind-mount:   /etc/containers/systemd/caddy.container
#
# The web root is bind-mounted read-only into the Caddy container and
# served by file_server, which picks up changes immediately — so a plain
# file copy is all that's needed (no container restart).
set -euo pipefail

SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEST_DIR="/var/lib/caddy/www/metronome"
DIST_DIR="$SRC_DIR/dist"

[[ -f "$SRC_DIR/index.html" ]] || { echo "error: $SRC_DIR/index.html not found" >&2; exit 1; }
[[ -d "$DEST_DIR" ]] || { echo "error: web root $DEST_DIR is missing — is Caddy set up?" >&2; exit 1; }

# Assemble the self-contained pages (inlines assets/ into dist/). dist/ is git-ignored.
"$SRC_DIR/build.sh"
[[ -f "$DIST_DIR/index.html" ]] || { echo "error: build did not produce $DIST_DIR/index.html" >&2; exit 1; }

# --- compute build version ---------------------------------------------------
# Formal build: clean tree on a commit tagged v<VERSION>  -> "X.Y.Z"
# Dev build:    anything else                             -> "X.Y.Z-dev.<utc-ts>.<sha>[.dirty]"
VER="$(cat "$SRC_DIR/VERSION" 2>/dev/null || echo 0.0.0)"
cd "$SRC_DIR"
if git rev-parse --git-dir >/dev/null 2>&1; then
  tag="$(git describe --exact-match --tags HEAD 2>/dev/null || true)"
  dirty=""; [[ -n "$(git status --porcelain 2>/dev/null)" ]] && dirty=".dirty"
  if [[ "$tag" == "v$VER" && -z "$dirty" ]]; then
    BUILD="$VER"                                            # formal release
  else
    BUILD="$VER-dev.$(date -u +%Y%m%dT%H%M%SZ).g$(git rev-parse --short HEAD 2>/dev/null || echo nogit)$dirty"
  fi
else
  BUILD="$VER-dev.$(date -u +%Y%m%dT%H%M%SZ)"               # not a git checkout
fi

# stamp the version into the built copy only (source stays clean)
echo "deployed v$BUILD -> $DEST_DIR"
for f in index.html editor.html editor-beta.html pm_e-2.html player.html mobile.html mobile-sessions.html teacher.html stage.html micro.html showcase.html kit.html explorer.html grid.html \
         embed.html \
         info-editor.html info-pm_e-2.html info-player.html info-teacher.html info-stage.html info-micro.html info-showcase.html info-kit.html info-explorer.html info-grid.html; do
  sed "s|const APP_VERSION = \"[^\"]*\";|const APP_VERSION = \"$BUILD\";|" "$DIST_DIR/$f" > "$DEST_DIR/$f"
  echo "  $f ($(stat -c '%s' "$DEST_DIR/$f") bytes)"
done
cp "$DIST_DIR/embed.js" "$DEST_DIR/embed.js"; echo "  embed.js ($(stat -c '%s' "$DEST_DIR/embed.js") bytes)"
# PWA assets for mobile.html (manifest + service worker + icons) — served at the web root
for f in manifest.webmanifest mobile-sw.js icon-192.png icon-512.png icon-180.png; do
  cp "$DIST_DIR/$f" "$DEST_DIR/$f"; echo "  $f ($(stat -c '%s' "$DEST_DIR/$f") bytes)"
done
cp "$DIST_DIR/pico-main.py" "$DEST_DIR/pico-main.py"; echo "  pico-main.py ($(stat -c '%s' "$DEST_DIR/pico-main.py") bytes)"  # PM_K-1 firmware download
# Rust firmware (RP2350) — served if built via rust/pm-kit/build.sh (gitignored artifact, not in dist/)
if [[ -f "$SRC_DIR/rust/pm-kit/pm-kit.uf2" ]]; then
  cp "$SRC_DIR/rust/pm-kit/pm-kit.uf2" "$DEST_DIR/pm-kit.uf2"
  echo "  pm-kit.uf2 ($(stat -c '%s' "$DEST_DIR/pm-kit.uf2") bytes)  # Rust RP2350 firmware (alpha live metronome)"
fi
# ELF with defmt info — `probe-rs run --chip RP235x pm-kit.elf` flashes over the Debug Probe and
# streams logs/panics. Needed locally (not the uf2) because defmt decodes log strings from the ELF.
if [[ -f "$SRC_DIR/rust/pm-kit/pm-kit.elf" ]]; then
  cp "$SRC_DIR/rust/pm-kit/pm-kit.elf" "$DEST_DIR/pm-kit.elf"
  echo "  pm-kit.elf ($(stat -c '%s' "$DEST_DIR/pm-kit.elf") bytes)  # probe-rs flash + defmt RTT logging"
fi
# Rust firmware (RP2040 / Pico Scroll Pack) — served if built via rust/pm-grid/build.sh (gitignored).
# BOOTSEL-drag pm-grid.uf2 onto the RPI-RP2 drive to flash the PM_G-1 Grid LED metronome.
if [[ -f "$SRC_DIR/rust/pm-grid/pm-grid.uf2" ]]; then
  cp "$SRC_DIR/rust/pm-grid/pm-grid.uf2" "$DEST_DIR/pm-grid.uf2"
  echo "  pm-grid.uf2 ($(stat -c '%s' "$DEST_DIR/pm-grid.uf2") bytes)  # Rust RP2040 firmware (the PM_G-1 Grid)"
fi
# ELF with defmt info — `probe-rs run --chip RP2040 pm-grid.elf` flashes over the Pi Debug Probe and
# streams defmt RTT logs/panics (decoded from the ELF). Served for local probe-based debugging.
if [[ -f "$SRC_DIR/rust/pm-grid/pm-grid.elf" ]]; then
  cp "$SRC_DIR/rust/pm-grid/pm-grid.elf" "$DEST_DIR/pm-grid.elf"
  echo "  pm-grid.elf ($(stat -c '%s' "$DEST_DIR/pm-grid.elf") bytes)  # probe-rs flash + defmt RTT logging"
fi
cp "$DIST_DIR/pm_k1_circuitpy.zip" "$DEST_DIR/pm_k1_circuitpy.zip"; echo "  pm_k1_circuitpy.zip ($(stat -c '%s' "$DEST_DIR/pm_k1_circuitpy.zip") bytes)"  # PM_K-1 CircuitPython bundle
cp "$DIST_DIR/pico-cp-app.py" "$DEST_DIR/pico-cp-app.py"; echo "  pico-cp-app.py ($(stat -c '%s' "$DEST_DIR/pico-cp-app.py") bytes)"  # served for version reading + reference
cp "$DIST_DIR/pico-cp-app.mpy" "$DEST_DIR/pico-cp-app.mpy"; echo "  pico-cp-app.mpy ($(stat -c '%s' "$DEST_DIR/pico-cp-app.mpy") bytes)"  # precompiled firmware the editor pushes (base64)
cp "$DIST_DIR/pm_x1_circuitpy.zip" "$DEST_DIR/pm_x1_circuitpy.zip"; echo "  pm_x1_circuitpy.zip ($(stat -c '%s' "$DEST_DIR/pm_x1_circuitpy.zip") bytes)"  # PM_X-1 Explorer CircuitPython bundle
cp "$DIST_DIR/pico-explorer-app.py" "$DEST_DIR/pico-explorer-app.py"; echo "  pico-explorer-app.py ($(stat -c '%s' "$DEST_DIR/pico-explorer-app.py") bytes)"  # served for version reading
cp "$DIST_DIR/pico-explorer-app.mpy" "$DEST_DIR/pico-explorer-app.mpy"; echo "  pico-explorer-app.mpy ($(stat -c '%s' "$DEST_DIR/pico-explorer-app.mpy") bytes)"  # PM_X-1 firmware (the editor pushes this when device id = X)
# PM_G-1 Grid is the native Rust firmware now (pm-grid.uf2 above) — the CircuitPython grid
# artifacts (pm_g1_circuitpy.zip / pico-scroll-app.{py,mpy}) are no longer built or served.
rm -f "$DEST_DIR/pm_g1_circuitpy.zip" "$DEST_DIR/pico-scroll-app.py" "$DEST_DIR/pico-scroll-app.mpy"  # remove stale Python grid downloads
rm -f "$DEST_DIR/player-asbuilt.html"        # renamed to teacher.html
rm -f "$DEST_DIR/concepts.html"              # Concepts is now the landing (/)
# info-*.html are first-class pages again: each form factor has a lean widget page
# (<device>.html) + a separate spec/BOM page (info-<device>.html that embeds it).

# If real audio samples are added later (see the plan's GM-sample note),
# sync that directory too.
if [[ -d "$SRC_DIR/samples" ]]; then
  rsync -a --delete "$SRC_DIR/samples/" "$DEST_DIR/samples/"
  echo "synced samples/ -> $DEST_DIR/samples"
fi

# Smoke test: Caddy serves on :8443 with tls internal; resolve the host
# to localhost so SNI matches the site block.
if command -v curl >/dev/null 2>&1; then
  code=$(curl -sk --resolve metronome.varasys.io:8443:127.0.0.1 \
    https://metronome.varasys.io:8443/ -o /dev/null -w '%{http_code}' || echo "??")
  echo "smoke test: metronome.varasys.io -> HTTP $code"
fi
