# 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.
#
# ---- Base OS ----
FROM debian:trixie-slim AS base

# Bump this to force an update of the apt repositories
ENV MIN_UPDATE_DATE="2026-06-05"

RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get upgrade -y
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
    ca-certificates
rm -rf /var/lib/apt/lists/*
EOR

ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1

WORKDIR /app


# ---- uv + managed Python + build system deps ----
FROM base AS uv

# Pin uv by SHA256 digest for supply chain security. We pull a newer uv than
# src/backend/Dockerfile (0.11.10): uv 0.11.10 only knows Python 3.14.5rc1,
# and python-build-standalone shipped 3.14.5 final on 2026-05-10 — which
# only landed in uv from 0.11.16 onward.
# Verify with: gh attestation verify --owner astral-sh oci://ghcr.io/astral-sh/uv:0.11.19
COPY --from=ghcr.io/astral-sh/uv@sha256:b46b03ddfcfbf8f547af7e9eaefdf8a39c8cebcba7c98858d3162bd28cf536f6 /uv /uvx /bin/

RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
    ca-certificates \
    build-essential
rm -rf /var/lib/apt/lists/*
EOR

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_PYTHON_PREFERENCE=only-managed
ENV UV_PYTHON_INSTALL_DIR=/opt/python
ENV UV_PROJECT_ENVIRONMENT=/venv

# Install Python via uv — integrity verified against SHA256 checksums embedded in the uv binary.
# Uses python-build-standalone: most C deps (ssl, ffi, sqlite, zlib, lzma, bz2) are statically linked.
RUN uv python install 3.14.5


# ---- 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 production (remove pip, idle, tkinter, tcl, headers, tests) ----
FROM uv AS python-runtime
RUN <<EOR
set -e
PYDIR=$(dirname $(dirname $(uv python find 3.14.5)))
rm -rf \
    $PYDIR/bin/idle* $PYDIR/bin/pip* $PYDIR/bin/pydoc* $PYDIR/bin/*-config \
    $PYDIR/include $PYDIR/share \
    $PYDIR/lib/pkgconfig $PYDIR/lib/itcl* $PYDIR/lib/libtcl* \
    $PYDIR/lib/tcl* $PYDIR/lib/tk* $PYDIR/lib/thread* \
    $PYDIR/lib/python3.14/idlelib \
    $PYDIR/lib/python3.14/ensurepip \
    $PYDIR/lib/python3.14/tkinter \
    $PYDIR/lib/python3.14/turtledemo \
    $PYDIR/lib/python3.14/lib-dynload/_tkinter* \
    $PYDIR/lib/python3.14/lib-dynload/_ctypes_test* \
    /opt/python/.gitignore /opt/python/.lock /opt/python/.temp
EOR


# ---- Base runtime image (slim) ----
FROM base 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 Python installation (with headers, pip — useful for debugging)
COPY --from=uv /opt/python /opt/python
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 base AS app-prod
COPY ./src /app/src


# ---- Production runtime (slim) ----
FROM runtime-base AS runtime-prod

COPY --from=python-runtime /opt/python /opt/python
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()"]
