# WiFi-DensePose Rust Sensing Server
# Includes RuVector signal intelligence crates
# Multi-stage build for minimal final image

# Stage 1: Build
FROM rust:1.89-bookworm AS builder

WORKDIR /build

# Copy workspace files
COPY v2/Cargo.toml v2/Cargo.lock ./
COPY v2/crates/ ./crates/

# Copy vendored RuVector crates
COPY vendor/ruvector/ /build/vendor/ruvector/

# Copy vendored RuField submodule — the `wifi-densepose-rufield` bridge crate
# (ADR-262) path-deps `../../../vendor/rufield/crates/*`, which from the Docker
# build layout (v2/ collapsed into /build) resolves to /vendor/rufield. Copy the
# whole tree so the rufield workspace Cargo.toml (workspace-dep inheritance) and
# the four bridged crates (rufield-core/-provenance/-privacy/-fusion) all resolve.
COPY vendor/rufield/ /vendor/rufield/

# Build release binaries:
#   - sensing-server with `mqtt` feature so the HA-DISCO MQTT publisher
#     (ADR-115) is wired in (auto-discovery topics flow to Home Assistant)
#   - cog-ha-matter, the ADR-116 Cognitum cog that wraps HA-DISCO +
#     HA-MIND + mDNS + embedded broker for Home Assistant / Matter
#   - homecore-server, the ADRs-126-134 HOMECORE native Rust port of
#     Home Assistant (HA-wire-compat REST + WebSocket on :8123,
#     SQLite + ruvector recorder, automation, assist, plugins, HAP)
RUN cargo build --release -p wifi-densepose-sensing-server --features mqtt 2>&1 \
 && cargo build --release -p cog-ha-matter 2>&1 \
 && cargo build --release -p homecore-server 2>&1 \
 && strip target/release/sensing-server target/release/cog-ha-matter target/release/homecore-server

# Stage 2: Runtime
FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy binaries
COPY --from=builder /build/target/release/sensing-server /app/sensing-server
COPY --from=builder /build/target/release/cog-ha-matter /app/cog-ha-matter
COPY --from=builder /build/target/release/homecore-server /app/homecore-server

# Copy UI assets
COPY ui/ /app/ui/

# Sanity-check the assets the runtime actually serves (regression guard for
# #520/#514 — the published image must include the observatory and pose-fusion
# dashboards, not just the legacy `index.html` set). Build fails if any of
# these are missing, so a stale image can't be silently pushed.
RUN set -e; \
    for f in /app/ui/index.html /app/ui/observatory.html /app/ui/pose-fusion.html /app/ui/viz.html; do \
        test -f "$f" || { echo "FATAL: missing UI asset $f"; exit 1; }; \
    done; \
    for d in /app/ui/observatory /app/ui/pose-fusion /app/ui/components /app/ui/services; do \
        test -d "$d" || { echo "FATAL: missing UI directory $d"; exit 1; }; \
    done; \
    test -x /app/sensing-server || { echo "FATAL: /app/sensing-server is not executable"; exit 1; }; \
    test -x /app/cog-ha-matter || { echo "FATAL: /app/cog-ha-matter is not executable"; exit 1; }; \
    test -x /app/homecore-server || { echo "FATAL: /app/homecore-server is not executable"; exit 1; }; \
    echo "image assets OK"

# Optional bearer-token auth on /api/v1/*: leave unset for LAN-mode (default),
# set to enforce `Authorization: Bearer <token>` (see bearer_auth module, #443).
#   docker run -e RUVIEW_API_TOKEN=$(openssl rand -hex 32) ...
ENV RUVIEW_API_TOKEN=

# HTTP API
EXPOSE 3000
# WebSocket
EXPOSE 3001
# ESP32 UDP
EXPOSE 5005/udp
# MQTT broker (cog-ha-matter embedded broker — Home Assistant + Matter)
EXPOSE 1883
# HOMECORE HA-compatible REST + WebSocket (homecore-server)
EXPOSE 8123

ENV RUST_LOG=info

# CSI_SOURCE controls which data source the sensing server uses at startup.
# auto      — probe UDP port 5005 for an ESP32 first; fall back to simulation (default)
# esp32     — receive real CSI frames from an ESP32 device over UDP port 5005
# wifi      — use host Wi-Fi RSSI/scan data (Windows netsh; not available in containers)
# simulated — generate synthetic CSI frames (no hardware required)
# Override at runtime:  docker run -e CSI_SOURCE=esp32 ...
ENV CSI_SOURCE=auto

# MODELS_DIR controls where the server scans for .rvf model files.
# Mount a host directory here to make models visible to the API:
#   docker run -v /path/to/models:/app/models -e MODELS_DIR=/app/models ...
ENV MODELS_DIR=data/models

COPY docker/docker-entrypoint.sh /app/docker-entrypoint.sh

# Exec-form ENTRYPOINT so Docker appends user arguments correctly.
# Pass flags directly:  docker run <image> --source esp32 --tick-ms 500
# Or use env vars:      docker run -e CSI_SOURCE=esp32 <image>
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD []
