# ============================================================
# Multi-stage build for MCP Task Orchestrator
# ============================================================

# --- Builder stage ---
FROM eclipse-temurin:21-jdk AS builder

WORKDIR /app

# Gradle wrapper and build configuration (cached aggressively)
COPY gradlew gradlew.bat ./
COPY gradle gradle
COPY build.gradle.kts settings.gradle.kts gradle.properties ./
COPY version.properties ./
COPY current/build.gradle.kts current/
RUN sed -i 's/\r$//' gradlew && chmod +x gradlew

# Download dependencies (cached until build files change)
RUN ./gradlew dependencies --no-daemon

# Source code (changes frequently, placed last for cache)
COPY current/src current/src

RUN ./gradlew :current:jar --no-daemon -x test

# --- Runtime base stage (shared configuration for all runtime targets) ---
FROM amazoncorretto:25-al2023-headless AS runtime-base

# Bases: the builder stage is eclipse-temurin:21-jdk; the runtime is Amazon Corretto 25 on AL2023 (headless),
# which addresses high severity CVEs seen in earlier Temurin runtime images.
# Using headless variant (runtime-only, no GUI libraries) for optimal production container size

LABEL org.opencontainers.image.title="MCP Task Orchestrator" \
      org.opencontainers.image.description="Kotlin MCP server for hierarchical task management with AI assistants" \
      org.opencontainers.image.url="https://github.com/jpicklyk/task-orchestrator" \
      org.opencontainers.image.source="https://github.com/jpicklyk/task-orchestrator" \
      org.opencontainers.image.vendor="jpicklyk" \
      org.opencontainers.image.licenses="MIT" \
      io.modelcontextprotocol.server.name="io.github.jpicklyk/task-orchestrator"

WORKDIR /app

# Create non-root user and required directories
# shadow-utils provides groupadd/useradd on AL2023 minimal images
RUN dnf install -y shadow-utils \
    && dnf clean all \
    && groupadd -r -g 1001 appgroup \
    && useradd -r -u 1001 -g appgroup -d /app -s /sbin/nologin appuser \
    && mkdir -p /app/data \
    && chown -R appuser:appgroup /app

# Volume for SQLite database persistence
VOLUME /app/data

# Environment variables (only those consumed by the application)
ENV MCP_TRANSPORT=stdio
ENV LOG_LEVEL=INFO
ENV AGENT_CONFIG_DIR=/project
ENV MCP_HTTP_HOST=0.0.0.0
ENV MCP_HTTP_PORT=3001
ENV READINESS_FILE=/tmp/mcp-task-orchestrator.ready
EXPOSE 3001

# Switch to non-root user
USER appuser

# Signal Docker to send SIGTERM for graceful shutdown
STOPSIGNAL SIGTERM

# Health check: the readiness marker at $READINESS_FILE is written only after the server has
# actually started serving (stdio session created / HTTP listener started) and removed on every
# shutdown path, so "file present" == "actually serving" for either transport. A marker file is
# used instead of an HTTP probe because this runtime image has no curl/wget, and /api/v1/health
# only exists under MCP_TRANSPORT=http with API_ENABLED=true (default transport is stdio).
HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \
    CMD sh -c 'test -f "$READINESS_FILE"'

# Run the MCP server
# --enable-native-access=ALL-UNNAMED: Required for SQLite JDBC native library loading in Java 25+
# -Duser.timezone=UTC: pins the JVM default timezone so claim TTL/expiry comparisons (Exposed
#   `timestamp` columns vs SQLite datetime('now')) are computed against the same clock regardless of
#   host/container timezone config. Non-Docker launches (`java -jar`) get the same guarantee via
#   JvmTimezone.enforceUtc() in CurrentMain, which overrides a non-UTC default with a WARN.
CMD ["java", "-Dfile.encoding=UTF-8", "-Djava.awt.headless=true", "-Duser.timezone=UTC", "--enable-native-access=ALL-UNNAMED", "-jar", "orchestrator.jar"]

# --- runtime-current target (4.0 Current - active) ---
FROM runtime-base AS runtime-current
COPY --from=builder --chown=appuser:appgroup /app/current/build/libs/mcp-task-orchestrator-current-*.jar /app/orchestrator.jar
ENV DATABASE_PATH=data/current-tasks.db
