# Subtitle OCR v13.0.9
# Python is the actual application runtime; .NET is only needed by SeConv itself,
# which is shipped as a self-contained native executable.
FROM python:3.12-slim-bookworm

ARG SE_VERSION=5.2.0

ENV DEBIAN_FRONTEND=noninteractive \
    PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1 \
    MEDIA_ROOT=/media \
    CONFIG_ROOT=/config \
    WEB_PORT=8787

# Keep the runtime image small and install only what the application needs.
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        ca-certificates \
        curl \
        tar \
        mkvtoolnix \
        tesseract-ocr \
        tesseract-ocr-nld \
        tesseract-ocr-eng \
        libfontconfig1 \
        libfreetype6 \
        libglib2.0-0 \
        libx11-6 \
        libxext6 \
        libxrender1; \
    rm -rf /var/lib/apt/lists/*

# Download the SeConv CLI for the container architecture.
# NOTE: SeConv assets are added manually to Subtitle Edit releases (separate
# GitHub workflow), so they are not present on every tag. The download therefore
# tries SECONV_TAG first (if set), then v${SE_VERSION}, then ${SE_VERSION}.
# We also try to fetch the matching full Subtitle Edit Linux bundle to pick up
# SeConv's native Skia/HarfBuzz/Oniguruma libraries; that step is optional and
# the final `seconv --help` check fails the build if libraries are missing.
# SHA-256: when SECONV_SHA256 / SUBTITLEEDIT_SHA256 are set the download is
# verified against them; otherwise the computed hash is printed in the build log.
ARG SECONV_TAG=""
ARG SECONV_SHA256=""
ARG SUBTITLEEDIT_SHA256=""
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
    LD_LIBRARY_PATH=/opt/seconv

RUN set -eux; \
    arch="$(dpkg --print-architecture)"; \
    case "${arch}" in \
        amd64) seconv_asset='SeConv-Linux-x64.tar.gz'; full_asset='SubtitleEdit-Linux-x64.tar.gz' ;; \
        arm64) seconv_asset='SeConv-Linux-ARM64.tar.gz'; full_asset='SubtitleEdit-Linux-ARM64.tar.gz' ;; \
        *) echo "Unsupported Docker architecture: ${arch}" >&2; exit 1 ;; \
    esac; \
    base='https://github.com/SubtitleEdit/subtitleedit/releases/download'; \
    fetch() { \
        asset="$1"; out="$2"; shift 2; \
        for tag in "$@"; do \
            [ -n "${tag}" ] || continue; \
            if curl --fail --silent --show-error --location --retry 3 --retry-delay 2 --proto '=https' --tlsv1.2 "${base}/${tag}/${asset}" -o "${out}"; then \
                echo "Downloaded ${asset} from tag ${tag}"; return 0; \
            fi; \
        done; \
        return 1; \
    }; \
    verify() { \
        file="$1"; expected="$2"; \
        actual="$(sha256sum "${file}" | cut -d' ' -f1)"; \
        echo "SHA-256 of ${file}: ${actual}"; \
        if [ -n "${expected}" ] && [ "${expected}" != "${actual}" ]; then \
            echo "ERROR: SHA-256 mismatch for ${file} (expected ${expected})" >&2; return 1; \
        fi; \
        return 0; \
    }; \
    if ! fetch "${seconv_asset}" /tmp/seconv.tar.gz "${SECONV_TAG}" "v${SE_VERSION}" "${SE_VERSION}"; then \
        echo "ERROR: ${seconv_asset} was not found on GitHub for SE_VERSION=${SE_VERSION}." >&2; \
        echo "SeConv assets are not published on every release. Open https://github.com/SubtitleEdit/subtitleedit/releases," >&2; \
        echo "find a release that lists ${seconv_asset} and set SECONV_TAG (build arg) to that tag." >&2; \
        exit 1; \
    fi; \
    verify /tmp/seconv.tar.gz "${SECONV_SHA256}"; \
    mkdir -p /tmp/seconv /tmp/subtitleedit /opt/seconv; \
    tar -xzf /tmp/seconv.tar.gz -C /tmp/seconv; \
    if fetch "${full_asset}" /tmp/subtitleedit.tar.gz "${SECONV_TAG}" "v${SE_VERSION}" "${SE_VERSION}"; then \
        verify /tmp/subtitleedit.tar.gz "${SUBTITLEEDIT_SHA256}"; \
        tar -xzf /tmp/subtitleedit.tar.gz -C /tmp/subtitleedit; \
    else \
        echo "WARNING: ${full_asset} not found; continuing with the libraries bundled in SeConv."; \
    fi; \
    bin="$(find /tmp/seconv -type f -name seconv -print -quit)"; \
    test -n "${bin}"; \
    install -m 0755 "${bin}" /opt/seconv/seconv; \
    for lib in libSkiaSharp.so libHarfBuzzSharp.so libonigwrap.so; do \
        src="$(find /tmp/seconv /tmp/subtitleedit -type f -name "${lib}*" -print -quit)"; \
        if [ -n "${src}" ]; then install -m 0755 "${src}" "/opt/seconv/$(basename "${src}")"; fi; \
    done; \
    test -x /opt/seconv/seconv; \
    ln -sf /opt/seconv/seconv /usr/local/bin/seconv; \
    ldconfig; \
    /usr/local/bin/seconv --help >/dev/null; \
    rm -rf /tmp/seconv /tmp/subtitleedit /tmp/seconv.tar.gz /tmp/subtitleedit.tar.gz

WORKDIR /app

COPY requirements.txt ./
RUN python -m pip install --no-cache-dir -r requirements.txt

COPY app.py ./

RUN set -eux; \
    mkdir -p /media /config; \
    python -c "import ast; ast.parse(open('/app/app.py', encoding='utf-8').read()); print('Python syntax OK')"; \
    python -c "import flask, gunicorn; print('Python dependencies OK')"; \
    command -v tesseract >/dev/null; \
    command -v mkvmerge >/dev/null; \
    test -x /usr/local/bin/seconv

EXPOSE 8787

# The healthcheck lives in docker-compose.yml (one place; uses curl, which is installed above).

CMD ["gunicorn", "--bind", "0.0.0.0:8787", "--workers", "1", "--threads", "8", "--timeout", "0", "app:app"]
