# ============================================================================
# Smart CCTV Analytics — Dockerfile (DeepStream 9.1 + Triton 통합)
# Base: nvcr.io/nvidia/deepstream:9.1-triton-multiarch (linux/amd64 digest 고정)
# GPU: RTX Pro 4000 SFF Edition (24GB GDDR7 ECC, 단일 GPU 개발환경)
# OS: Ubuntu 24.04 LTS (container base via DeepStream 9.1)
# 필수 스택: CUDA 13.2 + TensorRT 10.16.x + NVIDIA Driver 595.58.03+
# 확장성: 추후 GPU 추가 시 docker-compose.yml deploy.resources.reservations.devices.count 증가
# ============================================================================

ARG DEEPSTREAM_BASE_DIGEST=sha256:f6fa0247da9290979cbb05749e7da9435d089c93db7c4dcfe85ba2488b5f4994
FROM nvcr.io/nvidia/deepstream:9.1-triton-multiarch@${DEEPSTREAM_BASE_DIGEST} AS base

LABEL maintainer="Contextra AI Team"
LABEL version="1.1.0"
LABEL description="Contextra AI Analytics — DeepStream/Triton Runtime"

# --------------------------------------------------------------------------
# Environment variables
# --------------------------------------------------------------------------
ENV DEBIAN_FRONTEND=noninteractive \
    LANG=en_US.UTF-8 \
    LC_ALL=en_US.UTF-8 \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    NVIDIA_DRIVER_CAPABILITIES=compute,utility,video \
    APP_HOME=/opt/contextra \
    GST_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/gstreamer-1.0/deepstream:/opt/nvidia/deepstream/deepstream/lib/gst-plugins \
    GST_PLUGIN_SCANNER=/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner

# --------------------------------------------------------------------------
# Stage 1: System dependencies (DeepStream 이미지에 GStreamer 포함됨)
# --------------------------------------------------------------------------
FROM base AS deps

RUN apt-get update && apt-get install -y --no-install-recommends \
        locales \
        curl \
        wget \
        git \
        libpq-dev \
        pkg-config \
        gstreamer1.0-tools \
        python3-gi \
        gir1.2-gst-plugins-base-1.0 \
        gir1.2-gstreamer-1.0 \
    && locale-gen en_US.UTF-8 \
    && rm -rf /var/lib/apt/lists/*

# DeepStream 9.1: 추가 미디어 코덱 설치 (CPU decode/encode fallback용)
RUN if [ -f /opt/nvidia/deepstream/deepstream/user_additional_install.sh ]; then \
        bash /opt/nvidia/deepstream/deepstream/user_additional_install.sh; \
    fi

# GStreamer scanner 바이너리 보존 — multi-stage 빌드에서 누락 방지
COPY --from=base /usr/lib/x86_64-linux-gnu/gstreamer1.0/ /usr/lib/x86_64-linux-gnu/gstreamer1.0/

# --------------------------------------------------------------------------
# Stage 2: Build RF-DETR nvinferserver Custom Processor
# --------------------------------------------------------------------------
FROM base AS rfdetr_processor_build

ARG DEEPSTREAM_BASE_DIGEST
COPY native/nvinferserver_rfdetr/ /tmp/nvinferserver_rfdetr/
RUN make -C /tmp/nvinferserver_rfdetr \
        BUILD_DIR=/tmp/nvinferserver_rfdetr/build \
        BASE_IMAGE_DIGEST=${DEEPSTREAM_BASE_DIGEST} \
        DEEPSTREAM_VERSION=9.1 \
        -j2 all

# --------------------------------------------------------------------------
# Stage 3: Python Runtime packages
# CUDA 13.2용 PyTorch와 일반 PyPI package의 index 경계를 분리한다.
# --------------------------------------------------------------------------
FROM deps AS python_deps

COPY docker/requirements-runtime.txt /tmp/contextra-deps/requirements-runtime.txt
COPY docker/constraints-runtime.txt /tmp/contextra-deps/constraints-runtime.txt

# GPU Frame의 DLPack 변환에 필요한 Torch는 공식 CUDA 13.2 index에서만 설치한다.
RUN pip install --no-cache-dir \
        --index-url https://download.pytorch.org/whl/cu132 \
        --constraint /tmp/contextra-deps/constraints-runtime.txt \
        torch

# 일반 Runtime package는 공식 PyPI와 검증된 constraints 조합을 사용한다.
RUN pip install --no-cache-dir \
        --requirement /tmp/contextra-deps/requirements-runtime.txt \
        --constraint /tmp/contextra-deps/constraints-runtime.txt \
    && rm -rf /tmp/contextra-deps

# DeepStream PyServiceMaker와 TensorRT는 Base image의 공식 설치를 사용한다.
# Offline RF-DETR 변환 환경은 Runtime image와 분리한다.

# Frame identity binding의 개발 dependency는 최종 image에 설치하지 않는다.
FROM base AS frame_metadata_build
RUN apt-get update && apt-get install -y --no-install-recommends python3-dev \
    && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir --index-url https://pypi.org/simple \
        --only-binary=:all: --no-deps --target /tmp/frame-pybind pybind11==2.13.6 \
        --report /tmp/frame-metadata-install.json
COPY native/frame_metadata/ /tmp/frame_metadata/
RUN make -C /tmp/frame_metadata BUILD_DIR=/tmp/frame_metadata/build \
        PYBIND_INCLUDE=/tmp/frame-pybind/pybind11/include

# 기존 Torch/SDK 설치 layer를 보존하고 Tracking 의존성만 추가한다.
FROM python_deps AS tracking_deps
COPY docker/requirements-tracking.txt /tmp/requirements-tracking.txt
RUN mkdir -p /opt/contextra/build-info \
    && pip freeze > /tmp/existing-packages.txt \
    && pip install --no-cache-dir --index-url https://pypi.org/simple --only-binary=:all: \
        --constraint /tmp/existing-packages.txt --requirement /tmp/requirements-tracking.txt \
        --report /opt/contextra/build-info/tracking-install.json \
    && pip freeze > /opt/contextra/build-info/runtime-packages.txt

# --------------------------------------------------------------------------
# Stage 3: Application
# --------------------------------------------------------------------------
FROM tracking_deps AS app

ENV APP_HOME=/opt/contextra \
    PYTHONPATH=/opt/contextra:${PYTHONPATH}

WORKDIR ${APP_HOME}

# Create application directories
RUN mkdir -p \
        ${APP_HOME}/app \
        ${APP_HOME}/configs \
        ${APP_HOME}/models \
        ${APP_HOME}/data/metadata \
        ${APP_HOME}/data/active-learning \
        ${APP_HOME}/logs \
        /etc/contextra

# Copy application source code
COPY app/ ${APP_HOME}/app/
COPY --from=frame_metadata_build --chmod=0555 \
    /tmp/frame_metadata/build/contextra_frame_meta*.so ${APP_HOME}/
COPY --from=frame_metadata_build --chmod=0555 \
    /tmp/frame_metadata/build/libcontextra_rtp_time.so /opt/nvidia/deepstream/deepstream/lib/gst-plugins/
COPY --from=frame_metadata_build /tmp/frame-metadata-install.json \
    ${APP_HOME}/build-info/frame-metadata-install.json

# RF-DETR tensor -> NvDsObjectMeta adapter. Build source and compiler stay in the builder stage.
COPY --from=rfdetr_processor_build --chmod=0555 \
    /tmp/nvinferserver_rfdetr/build/libcontextra_nvinferserver_rfdetr.so \
    ${APP_HOME}/lib/libcontextra_nvinferserver_rfdetr.so
COPY --from=rfdetr_processor_build --chmod=0555 \
    /tmp/nvinferserver_rfdetr/build/libcontextra_medium_preprocess.so \
    ${APP_HOME}/lib/libcontextra_medium_preprocess.so

# Copy configuration files
COPY configs/system_config.yaml /etc/contextra/system_config.yaml
COPY configs/camera_ptz_config.example.yaml /etc/contextra/camera_ptz_config.yaml

# Copy entrypoint scripts
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# Expose ports (DeepStream 9.1 SDK 표준 포트)
EXPOSE 5000
EXPOSE 8554

HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=5 \
    CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:${PORT:-5000}/ready', timeout=5)" || exit 1

# Set entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

# Default command (can be overridden in docker-compose)
CMD ["python", "-m", "app.main"]
