# collate service image — the objective file-comparison engine.
#
# Runs the FastAPI surface (`POST /v1/compare/plates`, `/healthz`, `/readyz`,
# `/v1/contract`). collate reuses codex-pdf for plate decode + the Ghostscript
# `tiffsep` separation render, so the runtime needs Ghostscript on PATH; without
# it the PDF side of a compare self-skips (plate-side facts only) rather than
# failing — but production should always ship gs.

FROM python:3.12-slim AS base

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    DEBIAN_FRONTEND=noninteractive \
    PIP_NO_CACHE_DIR=1 \
    PORT=8080 \
    COLLATE_AUTH_MODE=none

# Runtime system packages:
# - ghostscript (>=10) for the tiffsep separation render (codex's PDF path).
# - poppler-utils backs codex's pdftoppm/pdftotext fallbacks.
# - tini reaps zombie children spawned by gs.
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
        ghostscript \
        poppler-utils \
        tini \
        ca-certificates \
        curl \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install collate (pulls codex-pdf + fastapi + numpy + Pillow from the index).
COPY pyproject.toml README.md ./
COPY src ./src
RUN python -m pip install --upgrade pip \
 && pip install .

# Non-root runtime user.
RUN useradd --system --create-home --shell /usr/sbin/nologin collate
USER collate

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
    CMD curl -fsS "http://127.0.0.1:${PORT:-8080}/healthz" || exit 1

ENTRYPOINT ["/usr/bin/tini", "--"]
# gunicorn + uvicorn workers serving the FastAPI app. COLLATE_WORKERS defaults
# to 2 (safe for a 2-vCPU Railway hobby box); a plate compare can take a few
# seconds (gs render), so the worker timeout is generous.
CMD ["sh", "-c", "exec gunicorn -w ${COLLATE_WORKERS:-2} -k uvicorn.workers.UvicornWorker -b 0.0.0.0:${PORT:-8080} --timeout 180 --graceful-timeout 30 collate.api.main:app"]
