# OrchestrAD Docker Image
# Three-stage build: (1) compile the Next.js static export, (2) embed it into
# the Go binary, (3) ship a minimal Alpine runtime. The single resulting binary
# serves the full product UI plus the API on one port.

# ---------------------------------------------------------------------------
# Stage 1: build the frontend (Next.js static export -> frontend/out)
# Debian base avoids musl/sharp native-module friction; this stage is discarded.
# ---------------------------------------------------------------------------
FROM --platform=$BUILDPLATFORM node:22-bookworm-slim AS frontend
WORKDIR /frontend

# Install deps first for better layer caching. .npmrc carries
# legacy-peer-deps=true, which npm ci needs to resolve the React 19 RC peer
# graph, so it must be present before the install runs.
COPY frontend/package.json frontend/package-lock.json frontend/.npmrc ./
RUN npm ci --no-audit --no-fund

COPY frontend/ ./
RUN npm run build
# next.config.mjs sets output:"export", so the static site lands in ./out

# ---------------------------------------------------------------------------
# Stage 2: build the Go binary with the UI embedded
# ---------------------------------------------------------------------------
# Pinned to the *build* platform and cross-compiled with GOARCH below, so an
# arm64 image is produced natively on an amd64 runner with no QEMU emulation
# (which would make the Go build minutes-long instead of seconds).
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS builder

# Pure-Go SQLite (modernc.org/sqlite) means no C toolchain is needed, which is
# also what makes cross-compilation this simple.
RUN apk add --no-cache git

WORKDIR /build

# Cache modules first.
COPY backend/go.mod backend/go.sum* ./
RUN go mod download

# Copy source, then drop the staged UI into the embed directory. webui.go does
# //go:embed all:dist, so the compiled binary carries the real UI instead of
# the placeholder page.
COPY backend/ ./
COPY --from=frontend /frontend/out/ ./internal/webui/dist/

# Build with version info injected via ldflags.
ARG VERSION=dev
ARG BUILD_TIME=unknown
ARG GIT_COMMIT=unknown

# TARGETOS/TARGETARCH are supplied automatically by buildx for each --platform.
ARG TARGETOS
ARG TARGETARCH

RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} go build \
    -ldflags "-s -w \
        -X github.com/Grace-Solutions/OrchestrAD/internal/version.Version=${VERSION} \
        -X github.com/Grace-Solutions/OrchestrAD/internal/version.BuildTime=${BUILD_TIME} \
        -X github.com/Grace-Solutions/OrchestrAD/internal/version.GitCommit=${GIT_COMMIT}" \
    -o /orchestrad ./cmd/orchestrad

# ---------------------------------------------------------------------------
# Stage 3: minimal runtime
# ---------------------------------------------------------------------------
FROM alpine:3.19

RUN apk add --no-cache ca-certificates tzdata wget

# Create non-root user
RUN addgroup -g 1000 orchestrad && \
    adduser -u 1000 -G orchestrad -D orchestrad

WORKDIR /app

# Copy binary
COPY --from=builder /orchestrad /app/orchestrad

# Create data directories
RUN mkdir -p /data/logs /data/backups && \
    chown -R orchestrad:orchestrad /data

# Default environment
ENV ORCHESTRAD_DATA_PATH=/data
ENV ORCHESTRAD_LOG_LEVEL=info
# Containers typically sit behind an ingress/proxy that terminates TLS, so the
# image serves plain HTTP by default and the healthcheck below is HTTP. Set
# ORCHESTRAD_TLS_ENABLED=true to have the container manage its own certificate.
ENV ORCHESTRAD_TLS_ENABLED=false

# Expose port
EXPOSE 18090

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:18090/health || exit 1

# Switch to non-root user
USER orchestrad

# Default to foreground mode
ENTRYPOINT ["/app/orchestrad"]
CMD ["run"]
