# syntax=docker/dockerfile:1.7
# damascus-ui v1 — multi-stage build for the React 19 + Vite 6 + MUI 6
# dashboard (P4).
#
# Stage 1 (build):  node:22-alpine, install deps, run vite build.
# Stage 2 (output): minimal scratch-equivalent — just the static bundle
#                   is written to /opt/damascus/ui so the damascus-api
#                   container can mount it as a read-only volume and
#                   serve it with FastAPI's StaticFiles.
#
# Why a separate UI bundle image instead of building inside the
# damascus-api image: the P2 FastAPI service already exists in the main
# damascus-orchestrator image; baking Node.js + npm into it just to run
# a one-shot build would bloat the runtime image with build tools.
# One-shot build pattern matches the contract ("Builds the bundle,
# drops it into a named volume `damascus_ui`").
#
# Usage from docker-compose:
#   docker compose up damascus-ui-build    # runs to completion, then exits
#   docker compose up damascus-api         # mounts the volume and serves

ARG NODE_VERSION=22

# ---- Stage 1: build ------------------------------------------------------
FROM node:${NODE_VERSION}-alpine AS build

# pnpm or yarn aren't used here — package-lock.json drives npm ci.
WORKDIR /app

# Copy manifests first so dependency layer caches when only src changes.
COPY package.json package-lock.json* ./
# `npm ci` requires a lockfile; fall back to `npm install` in dev where
# the lockfile may not yet be committed.
RUN if [ -f package-lock.json ]; then \
      npm ci --no-audit --no-fund; \
    else \
      npm install --no-audit --no-fund; \
    fi

# Now copy the source.
COPY . .

# Default API target for dev — overridden in production by the
# same-origin FastAPI mount. The vite preview server uses this only
# when run standalone; the actual production bundle is served by the
# API container as same-origin so VITE_API_BASE_URL is empty in
# production builds (left to compose / CI to set).
ARG VITE_API_BASE_URL=""
ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}

RUN npm run build

# ---- Stage 2: output -----------------------------------------------------
# The build stage's `dist/` is the only thing the API container needs.
# A scratch-equivalent would be the leanest option, but an alpine stage
# makes it easier for compose bind-mounts and ad-hoc debugging.
#
# The bundle is written to /bundle (not /opt/damascus/ui) on purpose:
# the compose `damascus-ui-build` service mounts the named volume
# `damascus_ui` AT /bundle, which lets the bundle flow into the volume
# without a copy step. The P2 `damascus-api` service then mounts the
# same volume at /opt/damascus/ui:ro where FastAPI's StaticFiles can
# serve it.
FROM alpine:3.20 AS output

RUN mkdir -p /bundle
COPY --from=build /app/dist/ /bundle/

# Sanity: the bundle must contain an index.html
RUN test -f /bundle/index.html

# The bundle is static — no ENTRYPOINT, no EXPOSE. The named volume
# `damascus_ui` is what carries the files into the API container.
