# Frontend build stage
FROM registry.access.redhat.com/ubi9/nodejs-22-minimal AS frontend-builder

USER 0
WORKDIR /frontend

# Copy package files first for layer caching
COPY frontend/package.json frontend/package-lock.json ./

# Install dependencies
RUN npm ci

# Copy frontend source
COPY frontend/ .

# Build the frontend (vite build only — type checking runs in tox/CI)
RUN npx vite build

# Sidecar build stage
FROM registry.access.redhat.com/ubi9/nodejs-22-minimal AS sidecar-builder

USER 0
WORKDIR /sidecar

RUN microdnf install -y --nodocs --setopt=install_weak_deps=0 git && microdnf clean all

COPY sidecar-helper/package.json sidecar-helper/package-lock.json* ./
RUN npm ci

COPY sidecar-helper/ .
RUN npx tsc
RUN npm prune --omit=dev

FROM ghcr.io/astral-sh/uv:python3.14-bookworm-slim AS builder

WORKDIR /app

# Install git (needed for gitpython dependency)
RUN apt-get update && apt-get install -y --no-install-recommends \
    git \
    && rm -rf /var/lib/apt/lists/*

# Copy project files
COPY pyproject.toml uv.lock ./
COPY src/ src/

# Create venv and install dependencies
RUN uv sync --frozen --no-dev

# Production stage
FROM ghcr.io/astral-sh/uv:python3.14-bookworm-slim

WORKDIR /app

# Install bash, git (runtime for gitpython), curl (for Cursor CLI + NodeSource setup)
RUN apt-get update && apt-get install -y --no-install-recommends \
    bash \
    git \
    curl \
    ca-certificates \
    gnupg \
    && rm -rf /var/lib/apt/lists/*

# Pinned to 22.22.3 — Node 22.23.0+ has a keep-alive regression that breaks
# google-auth-library/gaxios/node-fetch@2 (https://github.com/nodejs/node/issues/63989)
# TODO: unpin once nodejs/node#63989 is resolved and a fixed 22.x release lands in NodeSource
ARG NODEJS_DEB_VERSION=22.22.3-1nodesource1
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN set -e \
    && NODESOURCE_FPR=6F71F525282841EEDAF851B42F59B5F99B1BE0B4 \
    && export GNUPGHOME="$(mktemp -d)" \
    && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key -o /tmp/nodesource.key \
    && gpg --show-keys --with-colons /tmp/nodesource.key | awk -F: '$1=="fpr"{print $10}' | grep -qx "$NODESOURCE_FPR" \
    && gpg --no-default-keyring --keyring /tmp/nodesource-tmp.gpg --import /tmp/nodesource.key \
    && gpg --no-default-keyring --keyring /tmp/nodesource-tmp.gpg --export "$NODESOURCE_FPR" > /tmp/nodesource-export.gpg \
    && gpg --dearmor -o /usr/share/keyrings/nodesource.gpg /tmp/nodesource-export.gpg \
    && rm -f /tmp/nodesource.key /tmp/nodesource-tmp.gpg /tmp/nodesource-tmp.gpg~ /tmp/nodesource-export.gpg \
    && rm -rf "$GNUPGHOME" \
    && echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" \
        > /etc/apt/sources.list.d/nodesource.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends nodejs=${NODEJS_DEB_VERSION} \
    && rm -f /etc/apt/sources.list.d/nodesource.list /usr/share/keyrings/nodesource.gpg \
    && rm -rf /var/lib/apt/lists/* \
    && node --version && npm --version
SHELL ["/bin/sh", "-c"]

# Create non-root user, data directory, and set permissions
# OpenShift runs containers as a random UID in the root group (GID 0)
RUN useradd --create-home --shell /bin/bash -g 0 appuser \
    && mkdir -p /data \
    && chown appuser:0 /data \
    && chmod -R g+w /data

# Switch to non-root user for CLI installs
USER appuser

# Install Cursor Agent CLI (installs to ~/.local/bin)
# Claude and Gemini are handled by the Pi SDK sidecar — no CLI needed
RUN /bin/bash -o pipefail -c "curl -fsSL https://cursor.com/install | bash"

# Configure npm for non-root global installs and install acpx CLI (needed by sidecar acpx-provider extension)
RUN mkdir -p /home/appuser/.npm-global \
    && npm config set prefix '/home/appuser/.npm-global' \
    && npm install -g acpx

# Switch to root for file copies and permission fixes
USER root

# Copy the virtual environment from builder
COPY --chown=appuser:0 --from=builder /app/.venv /app/.venv

# Copy project files needed by uv
COPY --chown=appuser:0 --from=builder /app/pyproject.toml /app/uv.lock ./

# Copy source code
COPY --chown=appuser:0 --from=builder /app/src /app/src

# Copy built frontend assets from frontend builder
COPY --chown=appuser:0 --from=frontend-builder /frontend/dist /app/frontend/dist

# Copy sidecar
COPY --chown=appuser:0 --from=sidecar-builder /sidecar/dist /app/sidecar-helper/dist
COPY --chown=appuser:0 --from=sidecar-builder /sidecar/node_modules /app/sidecar-helper/node_modules
COPY --chown=appuser:0 --from=sidecar-builder /sidecar/package.json /app/sidecar-helper/package.json

# Copy entrypoint script
COPY --chown=appuser:0 entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

# Make /app group-writable for OpenShift compatibility
RUN chmod -R g+w /app

# Make appuser home accessible by OpenShift arbitrary UID
# Only chmod directories (not files) — files are already group-readable by default.
# Directories need group write+execute for OpenShift's arbitrary UID (in GID 0)
# to create config/cache files at runtime.
RUN find /home/appuser -type d -exec chmod g=u {} + \
    && npm cache clean --force 2>/dev/null; \
    rm -rf /home/appuser/.npm/_cacache

# Switch back to non-root user for runtime
USER appuser

# Ensure CLIs are in PATH
ENV PATH="/home/appuser/.local/bin:/home/appuser/.npm-global/bin:${PATH}"
# Set HOME for OpenShift compatibility (random UID has no passwd entry)
ENV HOME="/home/appuser"

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
    CMD curl -f http://localhost:${PORT:-8000}/health && curl -f http://localhost:${SIDECAR_PORT:-9100}/health || exit 1

# Use uv run for uvicorn
# --no-sync prevents uv from attempting to modify the venv at runtime.
# This is required for OpenShift where containers run as an arbitrary UID
# and may not have write access to the .venv directory.
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["uv", "run", "--no-sync", "uvicorn", "rootcoz.main:app", "--host", "0.0.0.0"]
