# ==============================================================================
# Multi-stage Dockerfile for Stirling-PDF – image with everything included
# Includes: LibreOffice, Calibre, Tesseract, OCRmyPDF, unoserver, WeasyPrint, etc.
# ==============================================================================

# ========================================
# STAGE 1: Build stage - Alpine with Gradle
# ========================================
FROM gradle:8.14-jdk21 AS build

COPY build.gradle .
COPY settings.gradle .
COPY gradlew .
COPY gradle gradle/
COPY app/core/build.gradle core/.
COPY app/common/build.gradle common/.
COPY app/proprietary/build.gradle proprietary/.
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0

# Set the working directory
WORKDIR /app

# Copy the entire project to the working directory
COPY . .

# Build the application (server-only JAR - no UI, includes security features controlled at runtime)
RUN DISABLE_ADDITIONAL_FEATURES=false \
    STIRLING_PDF_DESKTOP_UI=false \
    ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube

# ========================================
# STAGE 2: Runtime image based on Debian stable-slim
# Contains Java runtime + LibreOffice + Calibre + all PDF tools
# ========================================
FROM debian:stable-slim@sha256:7cb087f19bcc175b96fbe4c2aef42ed00733a659581a80f6ebccfd8fe3185a3d

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND=noninteractive

ENV TESS_BASE_PATH=/usr/share/tesseract-ocr/5/tessdata

# Install core runtime dependencies + tools required by Stirling-PDF features
RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates tzdata tini bash fontconfig \
    openjdk-21-jre-headless \
    ffmpeg poppler-utils ocrmypdf \
    libreoffice-nogui libreoffice-java-common \
    python3 python3-venv python3-uno \
    tesseract-ocr tesseract-ocr-eng tesseract-ocr-deu tesseract-ocr-fra \
    tesseract-ocr-por tesseract-ocr-chi-sim \
    libcairo2 libpango-1.0-0 libpangoft2-1.0-0 libgdk-pixbuf-2.0-0 \
    gosu unpaper \
    # AWT headless support (required for some Java graphics operations)
    libfreetype6 libfontconfig1 libx11-6 libxt6 libxext6 libxrender1 libxtst6 libxi6 \
    libxinerama1 libxkbcommon0 libxkbfile1 libsm6 libice6 \
    # Qt WebEngine dependencies for Calibre
    libegl1 libopengl0 libgl1 libxdamage1 libxfixes3 libxshmfence1 libdrm2 libgbm1 \
    libxkbcommon-x11-0 libxrandr2 libxcomposite1 libnss3 libx11-xcb1 \
    libxcb-cursor0 libdbus-1-3 libglib2.0-0 \
    # Virtual framebuffer (required for headless LibreOffice)
    xvfb x11-utils coreutils \
    # Temporary packages only needed for Calibre installer
    xz-utils gpgv curl xdg-utils \
    \
    # Install Calibre from official installer script
    && curl -fsSL https://download.calibre-ebook.com/linux-installer.sh | sh /dev/stdin \
    \
    # Clean up installer-only packages
    && apt-get purge -y xz-utils gpgv xdg-utils \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*

# Make ebook-convert available in PATH
RUN ln -sf /opt/calibre/ebook-convert /usr/bin/ebook-convert \
    && /opt/calibre/ebook-convert --version

# ==============================================================================
# Create non-root user (stirlingpdfuser) with configurable UID/GID
# ==============================================================================
ARG PUID=1000
ARG PGID=1000

RUN set -eux; \
    # Create group if it doesn't exist
    if ! getent group stirlingpdfgroup >/dev/null 2>&1; then \
    if getent group "${PGID}" >/dev/null 2>&1; then \
    groupadd -o -g "${PGID}" stirlingpdfgroup; \
    else \
    groupadd -g "${PGID}" stirlingpdfgroup; \
    fi; \
    fi; \
    # Create user if it doesn't exist, avoid UID conflicts
    if ! id -u stirlingpdfuser >/dev/null 2>&1; then \
    if getent passwd | awk -F: -v id="${PUID}" '$3==id{found=1} END{exit !found}'; then \
    echo "UID ${PUID} already in use – creating stirlingpdfuser with automatic UID"; \
    useradd -m -g stirlingpdfgroup -d /home/stirlingpdfuser -s /bin/bash stirlingpdfuser; \
    else \
    useradd -m -u "${PUID}" -g stirlingpdfgroup -d /home/stirlingpdfuser -s /bin/bash stirlingpdfuser; \
    fi; \
    fi

# Compatibility alias for older entrypoint scripts expecting su-exec
RUN ln -sf /usr/sbin/gosu /usr/local/bin/su-exec

# Copy application files from build stage
COPY --from=build --chown=stirlingpdfuser:stirlingpdfgroup /app/app/core/build/libs/*.jar /app.jar
COPY --from=build --chown=stirlingpdfuser:stirlingpdfgroup /app/build/libs/restart-helper.jar /restart-helper.jar
COPY scripts/ /scripts/
COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/truetype/

# Optional version tag (can be passed at build time)
ARG VERSION_TAG

LABEL org.opencontainers.image.title="Stirling-PDF Backend"
LABEL org.opencontainers.image.description="Backend service for Stirling-PDF - Java Spring Boot with PDF processing capabilities"
LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.vendor="Stirling-Tools"
LABEL org.opencontainers.image.url="https://www.stirlingpdf.com"
LABEL org.opencontainers.image.documentation="https://docs.stirlingpdf.com"
LABEL maintainer="Stirling-Tools"
LABEL org.opencontainers.image.authors="Stirling-Tools"
LABEL org.opencontainers.image.version="${VERSION_TAG}"
LABEL org.opencontainers.image.keywords="PDF, manipulation, backend, API, Spring Boot"

# ==============================================================================
# Runtime environment variables
# ==============================================================================
ENV VERSION_TAG=$VERSION_TAG \
    DISABLE_ADDITIONAL_FEATURES=true \
    JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 \
    -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 \
    -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70 \
    -Djava.awt.headless=true" \
    JAVA_CUSTOM_OPTS="" \
    HOME=/home/stirlingpdfuser \
    PUID=${PUID} \
    PGID=${PGID} \
    UMASK=022 \
    UNO_PATH=/usr/lib/libreoffice/program \
    STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \
    TMPDIR=/tmp/stirling-pdf \
    TEMP=/tmp/stirling-pdf \
    TMP=/tmp/stirling-pdf

# ==============================================================================
# Python virtual environment for additional Python tools (WeasyPrint, OpenCV, etc.)
# ==============================================================================
RUN python3 -m venv /opt/venv --system-site-packages \
    && /opt/venv/bin/pip install --no-cache-dir weasyprint pdf2image opencv-python-headless \
    && /opt/venv/bin/python -c "import cv2; print('OpenCV version:', cv2.__version__)"

# Separate venv for unoserver (keeps it isolated)
RUN python3 -m venv /opt/unoserver-venv --system-site-packages \
    && /opt/unoserver-venv/bin/pip install --no-cache-dir unoserver

# Make unoserver tools available in main venv PATH
RUN ln -sf /opt/unoserver-venv/bin/unoconvert /opt/venv/bin/unoconvert \
    && ln -sf /opt/unoserver-venv/bin/unoserver /opt/venv/bin/unoserver

# Extend PATH to include both virtual environments
ENV PATH="/opt/venv/bin:/opt/unoserver-venv/bin:${PATH}"

# ==============================================================================
# Final permissions, directories and font cache
# ==============================================================================
RUN set -eux; \
    chmod +x /scripts/*; \
    mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders /tmp/stirling-pdf; \
    chown -R stirlingpdfuser:stirlingpdfgroup \
    /home/stirlingpdfuser /configs /logs /customFiles /pipeline /tmp/stirling-pdf \
    /app.jar /restart-helper.jar /usr/share/fonts/truetype /scripts; \
    chmod -R 755 /tmp/stirling-pdf

# Rebuild font cache
RUN fc-cache -f -v

# Force Qt/WebEngine to run headlessly (required for Calibre in Docker)
ENV QT_QPA_PLATFORM=offscreen \
    QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu --disable-dev-shm-usage"

# Expose web UI port
EXPOSE 8080/tcp

STOPSIGNAL SIGTERM

# Use tini as init (handles signals and zombies correctly)
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]

# CMD is empty – actual start command is defined in init.sh
CMD []
