# ─── OpenBao CLI, copied from upstream image (multi-arch automatic) ───
# Update the tag here to adopt a newer OpenBao. Binary is statically linked,
# safe to drop into the Node alpine image as-is.
FROM openbao/openbao:2.5.3 AS bao-src

FROM node:20-alpine

WORKDIR /app

# ffmpeg: audio conversion for AWS Transcribe (WebM → PCM)
# curl:   download Whisper models for browser-based transcription
# jq:     JSON parsing for the entrypoint's OpenBao secret-fetch step
RUN apk add --no-cache ffmpeg curl jq

# Pull the bao CLI out of the upstream image — matches host arch because
# buildx pulls the right manifest-list variant per build.
COPY --from=bao-src /bin/bao /usr/local/bin/bao
RUN /usr/local/bin/bao version

COPY package.json package-lock.json .npmrc ./
# argon2 compiles native code via node-gyp — needs python3/make/g++ at build time.
# npm ci installs the exact versions from package-lock.json so a transitive
# peer-dep conflict (e.g. zod v4 vs openai's peerOptional zod@^3.x) can't
# break the image build — the lock file has already resolved it once.
# Install with devDeps so tsc is available for the compile step below.
RUN apk add --no-cache --virtual .build-deps python3 make g++ \
    && npm ci \
    && apk del .build-deps

COPY . .

# Compile TypeScript → dist/, then prune devDeps from node_modules to keep
# the final image slim. `server.ts` is the entry point (renamed from
# server.js in commit d60a29f); tsconfig emits to ./dist.
#
# Also copy package.json into dist/ — server.ts does `require('./package.json')`
# to read the app version at boot, which resolves relative to dist/server.js
# at runtime rather than the repo root. Keeping a copy alongside the compiled
# entry is simpler than making the source path-aware.
RUN npm run build \
    && cp package.json dist/package.json \
    && ln -s /app/public /app/dist/public \
    && npm prune --omit=dev

# Ensure the entrypoint is executable regardless of host file permissions
RUN chmod +x /app/docker-entrypoint.sh

RUN mkdir -p /app/data/logs

# Download Browser Whisper (COMPLETE self-hosting - zero CDN dependencies)
# Library + Models all bundled and served from our server
RUN mkdir -p /app/public/models/Xenova/whisper-tiny.en/onnx && \
    cd /app/public/models && \
    echo "Downloading transformers.js library (worker-compatible build)..." && \
    curl -sL -o transformers.min.js https://cdn.jsdelivr.net/npm/@xenova/transformers@2.0.0/dist/transformers.min.js && \
    cd Xenova/whisper-tiny.en && \
    echo "Downloading Whisper model files..." && \
    curl -sL -o config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/config.json && \
    curl -sL -o tokenizer.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/tokenizer.json && \
    curl -sL -o preprocessor_config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/preprocessor_config.json && \
    curl -sL -o generation_config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/generation_config.json && \
    curl -sL -o onnx/encoder_model_quantized.onnx https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/onnx/encoder_model_quantized.onnx && \
    curl -sL -o onnx/decoder_model_merged_quantized.onnx https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/onnx/decoder_model_merged_quantized.onnx && \
    echo "✅ Browser Whisper: 100% self-hosted (library: 760KB, models: 42MB)"

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1

# Entrypoint wrapper handles optional OpenBao secret fetch before exec'ing CMD.
# See docker-entrypoint.sh for the logic — it is a no-op if OPENBAO_ADDR is
# unset, so legacy .env-only deployments continue to work unchanged.
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["node", "dist/server.js"]

