# Multi-stage build: compile the wasm client + the server in one Rust
# image, then copy the artifacts into a tiny Debian runtime.
FROM rust:1-bookworm AS builder

# Pin wasm-bindgen-cli to the same version we use during development. If
# this number drifts from Cargo.lock the wasm load will fail.
ARG WASM_BINDGEN_VERSION=0.2.122

# Install the wasm32 target and wasm-bindgen-cli.
RUN rustup target add wasm32-unknown-unknown && \
    cargo install wasm-bindgen-cli --version ${WASM_BINDGEN_VERSION} --locked

WORKDIR /build

# Copy the whole project. The .dockerignore keeps target/ out so we get
# a clean release build inside the container.
COPY . .

# Build the wasm client (release) and run wasm-bindgen to emit the
# JS glue + bg.wasm into web/.
RUN cargo build --target wasm32-unknown-unknown --release --lib && \
    wasm-bindgen --target web --out-dir web --no-typescript \
        target/wasm32-unknown-unknown/release/voxel_game.wasm

# Build the multiplayer server.
RUN cd server && cargo build --release

# ---- Runtime image ----
FROM debian:bookworm-slim AS runtime

# ca-certificates lets the server speak HTTPS if it ever needs to (it
# doesn't yet, but it's tiny and avoids surprises). tini handles signal
# forwarding so `docker stop` is clean.
RUN apt-get update && \
    apt-get install -y --no-install-recommends ca-certificates tini && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=builder /build/server/target/release/voxel-server /usr/local/bin/voxel-server
COPY --from=builder /build/web /app/web

ENV STATIC_DIR=/app/web
ENV PORT=8080
EXPOSE 8080

# Run as non-root for safety.
RUN useradd --create-home --shell /bin/false --uid 10001 voxel && \
    chown -R voxel:voxel /app
USER voxel

ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["/usr/local/bin/voxel-server"]
