# Pure-Python inbound MTA image (aiosmtpd) — counterpart to ./Dockerfile
# (Postfix + milter). Both images share src/mta-in/pyproject.toml and live in
# parallel so the two implementations can be tested side-by-side. The Postfix
# image is the production default for now; this image will gradually replace
# it once parity is proven.
#
# Image layout mirrors src/backend/Dockerfile:
#   * debian:trixie-slim base (not python:slim — Python comes from uv).
#   * uv pinned by SHA256 digest for supply chain integrity.
#   * uv-managed python-build-standalone (most C deps statically linked).
#   * `python-runtime` stage strips pip/idle/tkinter/headers.
#   * `runtime-prod` (slim) and `runtime-distroless-prod` (cc-debian13:nonroot)
#     both available; the distroless variant is the security target.
#
# Shared base image (deploy/python-uv/Dockerfile): debian-trixie + apt upgrade +
# ca-certificates + uv (digest-pinned) + uv-managed CPython at /opt/python.
# Global ARG so it can be used in `FROM` below. Built by `make build-python-base`;
# overridden in CI.
ARG PYTHON_UV_IMAGE=messages-python-uv:local

# ---- uv + managed Python + build system deps ----
FROM ${PYTHON_UV_IMAGE} AS uv

# Build deps for compiling any C-extension wheels during `uv sync`.
RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
    build-essential
rm -rf /var/lib/apt/lists/*
EOR


# ---- Production dependencies ----
FROM uv AS base-with-deps

COPY pyproject.toml uv.lock ./

ENV PATH="/venv/bin:$PATH"

# No extras: the `postfix` extra (pymilter) needs libmilter-dev which is not
# present here, and we don't want it anyway.
RUN --mount=type=cache,target=/root/.cache/uv uv sync --locked --no-install-project --no-editable --no-dev


# ---- Development dependencies ----
FROM base-with-deps AS base-with-deps-dev

RUN --mount=type=cache,target=/root/.cache/uv uv sync --locked --no-install-project --no-editable --extra dev


# ---- Strip Python for the distroless image (see deploy/python-uv/strip-python.sh) ----
# Only runtime-distroless-prod (the real production target) uses this. The slim
# runtime-prod inherits the full managed Python from the shared base instead.
FROM ${PYTHON_UV_IMAGE} AS python-runtime
RUN strip-python


# ---- Base runtime image (slim) ----
# Inherits the shared base directly (full managed Python at /opt/python).
FROM ${PYTHON_UV_IMAGE} AS runtime-base

# Give the "root" group the same permissions as the "root" user on /etc/passwd
# to allow a user belonging to the root group to add new users; mirrors the
# backend pattern so DOCKER_USER bind-mount UIDs work in dev.
RUN chmod g=u /etc/passwd

# Un-privileged user running the application.
ARG DOCKER_USER=65532
USER ${DOCKER_USER}

ENV PATH="/venv/bin:$PATH"
ENV VIRTUAL_ENV=/venv
ENV VIRTUAL_ENV_PROMPT=venv

COPY ./entrypoint.pymta.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]


# ---- Development runtime ----
FROM runtime-base AS runtime-dev

# Full managed Python (with headers, pip) is already present from the shared base.
COPY --from=base-with-deps-dev /venv /venv

ENV PYTHONPATH="/app/src"

# /app will be mounted as a volume in the development container


# ---- Production application source (strip tests, dev tooling, build files) ----
FROM ${PYTHON_UV_IMAGE} AS app-prod
COPY ./src /app/src


# ---- Production runtime (slim) ----
FROM runtime-base AS runtime-prod
ARG DOCKER_USER=65532

# Hardening: whiteout pip/tkinter/tests/headers from the runtime (see
# strip-python). Does NOT shrink the image (full Python is in an inherited layer)
# but keeps those tools out of the running container. Strip as root so
# /opt/python stays root-owned (not writable by the app user), then restore it.
USER root
RUN strip-python
USER ${DOCKER_USER}

# The distroless target below copies in an already-stripped Python instead.
COPY --from=base-with-deps /venv /venv
COPY --from=app-prod /app/src /app/src

ENV PYTHONPATH="/app/src"

CMD ["python", "-m", "pymta.server"]

# Liveness probe: TCP-connect the SMTP listener. Uses stdlib socket — works in
# both slim and distroless variants without curl/nc.
HEALTHCHECK --interval=30s --timeout=2s --start-period=15s \
    CMD ["python", "-c", "import os, socket; s=socket.socket(); s.settimeout(1); s.connect(('127.0.0.1', int(os.getenv('PYMTA_SMTP_PORT', '25')))); s.close()"]


# ---- Distroless production runtime ----
# Uses cc-debian13 (C runtime only) + python-build-standalone from uv. No
# shell, no package manager, no busybox utilities. Runs as uid 65532.
# Debug with: docker run --entrypoint='' gcr.io/distroless/cc-debian13:debug-nonroot sh
FROM gcr.io/distroless/cc-debian13:nonroot AS runtime-distroless-prod

WORKDIR /app

# Stripped Python installation (python-build-standalone via uv)
COPY --from=python-runtime /opt/python /opt/python
# Python dependencies
COPY --from=base-with-deps /venv /venv
# Application code
COPY --from=app-prod /app/src /app/src

ENV PATH="/venv/bin:$PATH"
ENV VIRTUAL_ENV=/venv
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONPATH="/app/src"

# No shell entrypoint — distroless has no /bin/sh. The shell wrapper
# (entrypoint.pymta.sh) is only for dev-time EXEC_CMD modes.
CMD ["python", "-m", "pymta.server"]

HEALTHCHECK --interval=30s --timeout=2s --start-period=15s \
    CMD ["python", "-c", "import os, socket; s=socket.socket(); s.settimeout(1); s.connect(('127.0.0.1', int(os.getenv('PYMTA_SMTP_PORT', '25')))); s.close()"]
