# Multi-stage Dockerfile for the Xtablo Go backend.
#
# Three stages:
#   assets  — downloads Tailwind CLI, HTMX, and Sortable.js then compiles the
#             Tailwind output CSS from tailwind.input.css + templates/. (D-09)
#   builder — copies assets, runs `templ generate`, and compiles both binaries
#             with CGO_ENABLED=0 so they are fully static. (D-07)
#   runtime — copies only the two binaries into a minimal distroless image.
#             No CMD is set — docker-compose overrides command: per service. (D-08)
#
# Build context: backend/ directory (sibling to go.mod).
#   From the repo root:  docker build -f backend/Dockerfile backend/
#   From inside backend/: docker build .
#
# Security: no .env files are ever COPY'd into any layer (T-07-05).
# The :nonroot distroless tag runs as uid 65532, preventing filesystem writes (T-07-07).

# ---------------------------------------------------------------------------
# Stage 1: assets
# Downloads pinned versions of Tailwind CLI, HTMX, and Sortable.js,
# then compiles tailwind.input.css against templates/ for the minified CSS.
# ---------------------------------------------------------------------------
FROM node:20-alpine AS assets

WORKDIR /build

RUN apk add --no-cache curl

RUN mkdir -p static

# Tailwind standalone CLI — pinned at v4.0.0 (matches justfile tailwind_version)
RUN curl -sSL -o /usr/local/bin/tailwindcss \
    "https://github.com/tailwindlabs/tailwindcss/releases/download/v4.0.0/tailwindcss-linux-x64" \
    && chmod +x /usr/local/bin/tailwindcss

# HTMX — pinned at major version 2 (matches justfile htmx_version)
RUN curl -sSL -o static/htmx.min.js \
    "https://unpkg.com/htmx.org@2/dist/htmx.min.js"

# Sortable.js — pinned at v1.15.7 (matches justfile sortable_version)
RUN curl -sSL -o static/sortable.min.js \
    "https://cdn.jsdelivr.net/npm/sortablejs@1.15.7/Sortable.min.js"

# Copy Tailwind input and templates for content-scanning
COPY tailwind.input.css .
COPY templates/ templates/

# Compile and minify Tailwind CSS
RUN tailwindcss -i tailwind.input.css -o static/tailwind.css --minify

# ---------------------------------------------------------------------------
# Stage 2: builder
# Compiles both Go binaries (cmd/web and cmd/worker) with CGO_ENABLED=0.
# Runs `templ generate` first since *_templ.go files are gitignored. (D-07)
# ---------------------------------------------------------------------------
FROM golang:1.26-alpine AS builder

WORKDIR /app

# Download dependencies first (layer-cached until go.mod/go.sum change)
COPY go.mod go.sum ./
RUN go mod download

# Copy the entire backend context
COPY . .

# Overwrite static/ with the freshly built assets from the assets stage
COPY --from=assets /build/static ./static

# Install templ at the pinned version and run template generation
# (gitignored *_templ.go files must be generated at build time)
RUN go install github.com/a-h/templ/cmd/templ@v0.3.1020 && templ generate

# Compile the web server binary — CGO_ENABLED=0 required for distroless/static
RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -trimpath -o /app/web ./cmd/web

# Compile the background worker binary — CGO_ENABLED=0 required for distroless/static
RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -trimpath -o /app/worker ./cmd/worker

# ---------------------------------------------------------------------------
# Stage 3: runtime
# Minimal distroless image containing only the two compiled binaries.
# Runs as nonroot (uid 65532) — no filesystem write access. (T-07-07)
# No CMD set — docker-compose.prod.yaml provides `command:` per service. (D-08)
# ---------------------------------------------------------------------------
FROM gcr.io/distroless/static-debian12:nonroot

COPY --from=builder /app/web /app/web
COPY --from=builder /app/worker /app/worker

EXPOSE 8080
