# syntax=docker/dockerfile:1.7

# =============================================================================
# Stage 1 — builder (compile & sync deps with uv)
# =============================================================================
FROM python:3.12-slim-bookworm AS builder

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    UV_LINK_MODE=copy \
    UV_COMPILE_BYTECODE=1 \
    UV_PYTHON_DOWNLOADS=never \
    UV_PROJECT_ENVIRONMENT=/opt/venv

RUN apt-get update \
 && apt-get install -y --no-install-recommends \
        build-essential \
        curl \
        ca-certificates \
 && rm -rf /var/lib/apt/lists/*

# Install uv from the official static binary. Pinned to match the uv that
# generated uv.lock so `--frozen` and dependency-groups resolve identically.
COPY --from=ghcr.io/astral-sh/uv:0.11.14 /uv /usr/local/bin/uv

WORKDIR /app

# Resolve dependencies first (cached layer when only source changes)
COPY pyproject.toml uv.lock* ./
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-install-project --no-dev || \
    uv sync --no-install-project --no-dev

# Copy source and install the project itself
COPY src/ ./src/
COPY README.md LICENSE ./
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-dev || uv sync --no-dev

# Pre-install the spaCy model into the venv. We install the published wheel
# directly via `uv pip` rather than `python -m spacy download`, because the
# latter shells out to `pip`, which a uv-managed venv does not contain.
# The model version is pinned to match the spaCy 3.8.x line.
RUN --mount=type=cache,target=/root/.cache/uv \
    uv pip install --python /opt/venv/bin/python \
      "en_core_web_sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl"

# =============================================================================
# Stage 2 — runtime (slim, non-root)
# =============================================================================
FROM python:3.12-slim-bookworm AS runtime

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PATH="/opt/venv/bin:$PATH" \
    WORDFORGE_HOST=0.0.0.0 \
    WORDFORGE_PORT=8001

RUN apt-get update \
 && apt-get install -y --no-install-recommends \
        ca-certificates \
        tini \
 && rm -rf /var/lib/apt/lists/* \
 && groupadd --system --gid 1000 wordforge \
 && useradd  --system --uid 1000 --gid wordforge --home /app --shell /usr/sbin/nologin wordforge

# Copy the pre-built virtualenv from the builder
COPY --from=builder --chown=wordforge:wordforge /opt/venv /opt/venv

WORKDIR /app
COPY --chown=wordforge:wordforge src/ ./src/
COPY --chown=wordforge:wordforge README.md LICENSE pyproject.toml ./
COPY --chown=wordforge:wordforge docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh \
 && mkdir -p /app/data /app/data/cache \
 && chown -R wordforge:wordforge /app/data

USER wordforge

EXPOSE 8001

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD python -c "import urllib.request,sys; \
sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8001/health', timeout=3).status == 200 else 1)"

ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
CMD ["serve"]
