# Three stages: dump the OpenAPI schema, build the SPA against it, then run.
# Node exists only at build time; the running container is one Python process.

# --- stage 1: python deps + OpenAPI schema -----------------------------------
FROM python:3.12-slim AS pybuild
WORKDIR /build
RUN pip install --no-cache-dir --upgrade pip
COPY pyproject.toml ./
RUN pip install --no-cache-dir .
COPY app ./app
RUN python -c "import json,pathlib; from app.main import app; \
    pathlib.Path('openapi.json').write_text(json.dumps(app.openapi()))"

# --- stage 2: typed client + SPA build ---------------------------------------
FROM node:22-slim AS webbuild
WORKDIR /web
COPY web/package.json web/package-lock.json* ./
RUN npm install --no-audit --no-fund
COPY web/ ./
COPY --from=pybuild /build/openapi.json ./openapi.json
RUN npx openapi-typescript openapi.json -o src/api/schema.ts && npm run build

# --- stage 3: runtime ---------------------------------------------------------
FROM python:3.12-slim AS runtime
WORKDIR /srv/app
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
RUN pip install --no-cache-dir --upgrade pip
COPY pyproject.toml ./
RUN pip install --no-cache-dir .
COPY app ./app
# The review process document is READ at runtime by `services/process_doc.py` and shown on
# `/review`, so the page can never drift from the authority. Only this one doc ships; the rest
# of `docs/` stays out of the image.
COPY docs/REVIEW-PROCESS.md ./docs/REVIEW-PROCESS.md
# How a featured list is chosen is read the same way (`/how-we-choose`, Stream AW2).
COPY docs/FEATURED.md ./docs/FEATURED.md
# The privacy policy and the terms of use, read per request (services/process_doc.py `legal_page`).
COPY docs/legal ./docs/legal
COPY docs/AI-REVIEW-GUIDELINES.md ./docs/AI-REVIEW-GUIDELINES.md
COPY alembic.ini ./
COPY alembic ./alembic
COPY --from=webbuild /web/dist ./static
EXPOSE 8000
CMD ["sh", "-c", "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000"]
