#!/usr/bin/env bash
# Rebuild WASM artifacts and install them into solitaire_server/web/pkg/.
#
# Two artifacts are produced:
#   solitaire_wasm.*  — thin replay-viewer + interactive JS API (wasm-pack)
#   canvas.*          — full Bevy WASM app for play.html (cargo + wasm-bindgen)
#
# Prerequisites:
#   cargo install wasm-pack wasm-bindgen-cli
#   rustup target add wasm32-unknown-unknown
#   (optional) cargo install wasm-opt   # for smaller canvas_bg.wasm
#
# Run from the repo root:
#   ./build_wasm.sh
#
# The generated pkg/ files are committed to git so self-hosters who don't
# touch the WASM crates can skip this step.  Regenerate after any change to
# solitaire_wasm/, solitaire_web/, solitaire_engine/, or solitaire_core/.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUT_DIR="$REPO_ROOT/solitaire_server/web/pkg"

# Reproducible builds. The wasm artifacts otherwise bake in machine-specific
# absolute source paths (the cargo registry, the rustup std sources, and this
# checkout), so a rebuild on a different machine produces different bytes and
# the CI freshness gate (rebuild-and-diff) false-positives. Remap all three
# prefixes to fixed names so the output is byte-identical anywhere.
#
# We must use CARGO_ENCODED_RUSTFLAGS (not RUSTFLAGS) and re-state the
# getrandom backend cfg here: a `*_RUSTFLAGS` env var *replaces* — does not
# merge with — the `[target.wasm32-unknown-unknown] rustflags` in
# .cargo/config.toml, so dropping that cfg would break the wasm getrandom build.
# Keep this `--cfg` in sync with .cargo/config.toml.
CARGO_HOME_DIR="${CARGO_HOME:-$HOME/.cargo}"
RUSTUP_HOME_DIR="${RUSTUP_HOME:-$HOME/.rustup}"
US=$'\x1f'   # unit separator: CARGO_ENCODED_RUSTFLAGS arg delimiter
export CARGO_ENCODED_RUSTFLAGS="--cfg${US}getrandom_backend=\"wasm_js\"${US}--remap-path-prefix=${CARGO_HOME_DIR}=/cargo${US}--remap-path-prefix=${RUSTUP_HOME_DIR}=/rustup${US}--remap-path-prefix=${REPO_ROOT}=/build"

if ! command -v wasm-pack &> /dev/null; then
    echo "error: wasm-pack not found." >&2
    echo "  Install with: cargo install wasm-pack" >&2
    exit 1
fi

echo "Building solitaire_wasm (target: web)..."
wasm-pack build \
    --target web \
    --out-dir "$OUT_DIR" \
    --no-typescript \
    "$REPO_ROOT/solitaire_wasm"

# wasm-pack writes a package.json and .gitignore into the output dir.
# Remove them — we manage the output directory ourselves.
rm -f "$OUT_DIR/package.json" "$OUT_DIR/.gitignore"

# ---------------------------------------------------------------------------
# Bevy WASM app (solitaire_web → canvas.js + canvas_bg.wasm)
# ---------------------------------------------------------------------------

if ! command -v wasm-bindgen &> /dev/null; then
    echo "error: wasm-bindgen not found." >&2
    echo "  Install with: cargo install wasm-bindgen-cli" >&2
    echo "  The CLI version must match the wasm-bindgen crate dep." >&2
    exit 1
fi

echo "Building solitaire_web (Bevy WASM app)..."
# wasm-release is the size-focused profile (fat LTO, CGU=1, opt-level "s") —
# see [profile.wasm-release] in Cargo.toml. Download size is the constraint.
cargo build --profile wasm-release --target wasm32-unknown-unknown -p solitaire_web

echo "Running wasm-bindgen for solitaire_web..."
wasm-bindgen \
    --out-dir "$OUT_DIR" \
    --out-name canvas \
    --target web \
    --no-typescript \
    "$REPO_ROOT/target/wasm32-unknown-unknown/wasm-release/solitaire_web.wasm"

# Optional size optimisation — Bevy bundles are large (~5-15 MB uncompressed).
# wasm-opt passes are skipped silently when the tool is not installed.
if command -v wasm-opt &> /dev/null; then
    echo "Running wasm-opt on canvas_bg.wasm..."
    # Use -O2 (not -Oz): Bevy's render pipeline uses deep call stacks and
    # complex memory patterns that wasm-opt -Oz can miscompile, resulting
    # in a grey screen on first load. -O2 is speed-optimised and avoids
    # the size-focused transforms that trigger the regression.
    wasm-opt -O2 \
        -o "$OUT_DIR/canvas_bg.wasm" \
        "$OUT_DIR/canvas_bg.wasm"
else
    echo "note: wasm-opt not found; skipping size optimisation."
    echo "  Install with: cargo install wasm-opt  (or via binaryen)"
fi

echo "Done. Output:"
ls -lh "$OUT_DIR"
