FROM python:3.11-slim AS base

# uv from the official slim image (fast Python package manager).
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/

# Node.js 20 is needed at build time to compile TailwindCSS.
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
    && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
    && apt-get install -y --no-install-recommends nodejs \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Resolve Python deps from the project lockfile (only the `client` extra).
COPY pyproject.toml uv.lock ./
COPY .python-version ./
RUN uv sync --frozen --no-dev --extra client

# Copy the Flask app sources.
COPY src/frontend/flask_app/ ./flask_app/

# Build TailwindCSS (one-shot; no watcher in production image).
WORKDIR /app/flask_app
RUN npm install tailwindcss@3 && \
    npx tailwindcss -i static/css/input.css -o static/css/tailwind.css --minify

# Compile Flask-Babel translation catalogs.
RUN uv run --project /app pybabel compile -d translations

EXPOSE 5000

# Gunicorn behind Nginx/Traefik. Worker count and proxy trust kept in sync
# with the per-tablet rate-limiting fix (see V2.0.0 perf commit).
CMD ["uv", "run", "--project", "/app", "gunicorn", \
     "--workers", "5", \
     "--threads", "4", \
     "--worker-class", "gthread", \
     "--timeout", "60", \
     "--bind", "0.0.0.0:5000", \
     "--access-logfile", "-", \
     "--forwarded-allow-ips", "*", \
     "app:create_app()"]
